Est-ce que Swift a quelque chose comme _. FindWhere dans Underscore.js?
J'ai un tableau de structures de type T
et voudrais vérifier si le tableau contient un objet struct dont la propriété name
est égale à Foo
.
J'ai essayé d'utiliser find()
et filter()
, mais ils ne fonctionnent qu'avec des types primitifs, par ex. String
ou Int
. Lève une erreur sur le fait de ne pas se conformer au protocole Equitable
ou quelque chose comme ça.
FWIW, si vous ne souhaitez pas utiliser de fonction ou d’extension personnalisée, vous pouvez:
let array = [ .... ]
if let found = find(array.map({ $0.name }), "Foo") {
let obj = array[found]
}
Cela génère d'abord name
tableau, puis find
à partir de celui-ci.
Si vous avez un vaste choix, vous voudrez peut-être:
if let found = find(lazy(array).map({ $0.name }), "Foo") {
let obj = array[found]
}
ou peut-être:
if let found = find(lazy(array).map({ $0.name == "Foo" }), true) {
let obj = array[found]
}
Swift 5
Vérifier si l'élément existe
if array.contains(where: {$0.name == "foo"}) {
// it exists, do something
} else {
//item could not be found
}
récupère l'élément
if let foo = array.first(where: {$0.name == "foo"}) {
// do something with foo
} else {
// item could not be found
}
récupère l'élément et son offset
if let foo = array.enumerated().first(where: {$0.element.name == "foo"}) {
// do something with foo.offset and foo.element
} else {
// item could not be found
}
Obtenir le décalage
if let fooOffset = array.firstIndex(where: {$0.name == "foo"}) {
// do something with fooOffset
} else {
// item could not be found
}
Vous pouvez utiliser la méthode index
disponible sur Array
avec un prédicat ( voir la documentation d'Apple ici ).
func index(where predicate: (Element) throws -> Bool) rethrows -> Int?
Pour votre exemple spécifique, cela serait:
Swift 3.0
if let i = array.index(where: { $0.name == Foo }) {
return array[i]
}
Swift 2.0
if let i = array.indexOf({ $0.name == Foo }) {
return array[i]
}
Swift
Si vous avez besoin de l'utilisation de l'objet:
array.first{$0.name == "Foo"}
(Si vous avez plusieurs objets nommés "Foo", alors first
renverra le premier objet à partir d'un ordre non spécifié)
Swift 3.
if let index = array.index(where: { $0.name == "Foo" }) {
return array[index]
}
Swift 2.1
Le filtrage dans les propriétés d'objet est maintenant pris en charge dans Swift 2.1. Vous pouvez filtrer votre tableau en fonction de n'importe quelle valeur de la struct ou de la classe, voici un exemple
for myObj in myObjList where myObj.name == "foo" {
//object with name is foo
}
OR
for myObj in myObjList where myObj.Id > 10 {
//objects with Id is greater than 10
}
Vous pouvez filtrer le tableau, puis sélectionner le premier élément, comme indiqué dans Trouver un objet avec une propriété dans un tablea .
Ou vous définissez une extension personnalisée
extension Array {
// Returns the first element satisfying the predicate, or `nil`
// if there is no matching element.
func findFirstMatching<L : BooleanType>(predicate: T -> L) -> T? {
for item in self {
if predicate(item) {
return item // found
}
}
return nil // not found
}
}
Exemple d'utilisation:
struct T {
var name : String
}
let array = [T(name: "bar"), T(name: "baz"), T(name: "foo")]
if let item = array.findFirstMatching( { $0.name == "foo" } ) {
// item is the first matching array element
} else {
// not found
}
Dans Swift 3 , vous pouvez utiliser la méthode existante first(where:)
(comme mentionné dans un commentaire ):
if let item = array.first(where: { $0.name == "foo" }) {
// item is the first matching array element
} else {
// not found
}
Swift
vous pouvez utiliser index (où :) dans Swift 3
func index(where predicate: @noescape Element throws -> Bool) rethrows -> Int?
exemple
if let i = theArray.index(where: {$0.name == "Foo"}) {
return theArray[i]
}
Swift 4,
Une autre façon de réaliser cela en utilisant la fonction de filtre,
if let object = elements.filter({ $0.title == "title" }).first {
print("found")
} else {
print("not found")
}
Swift
if yourArray.contains(item) {
//item found, do what you want
}
else{
//item not found
yourArray.append(item)
}
Swift 2 ou plus tard
Vous pouvez combiner indexOf
et map
pour écrire une fonction "Rechercher élément" sur une seule ligne.
let array = [T(name: "foo"), T(name: "Foo"), T(name: "FOO")]
let foundValue = array.indexOf { $0.name == "Foo" }.map { array[$0] }
print(foundValue) // Prints "T(name: "Foo")"
L'utilisation de filter
+ first
semble plus nette, mais filter
évalue tous les éléments du tableau. indexOf
+ map
semble compliqué, mais l'évaluation s'arrête lorsque la première correspondance du tableau est trouvée. Les deux approches ont des avantages et des inconvénients.
Swift 3:
Vous pouvez utiliser la fonctionnalité intégrée Swifts pour rechercher des objets personnalisés dans un tableau.
Tout d'abord, vous devez vous assurer que votre objet personnalisé est conforme à: protocole compatible.
class Person : Equatable { //<--- Add Equatable protocol
let name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
//Add Equatable functionality:
static func == (lhs: Person, rhs: Person) -> Bool {
return (lhs.name == rhs.name)
}
}
Avec la fonctionnalité Equatable ajoutée à votre objet, Swift affiche désormais les propriétés supplémentaires que vous pouvez utiliser sur un tableau:
//create new array and populate with objects:
let p1 = Person(name: "Paul", age: 20)
let p2 = Person(name: "Mike", age: 22)
let p3 = Person(name: "Jane", age: 33)
var people = [Person]([p1,p2,p3])
//find index by object:
let index = people.index(of: p2)! //finds Index of Mike
//remove item by index:
people.remove(at: index) //removes Mike from array
Un autre moyen d’accéder à array.index (of: Any) consiste à déclarer votre objet.
import Foundation
class Model: NSObject { }
Utilisez contains
:
var yourItem:YourType!
if contains(yourArray, item){
yourItem = item
}
Vous pouvez aussi essayer ce que Martin vous a indiqué dans les commentaires et donner un autre essai à filter
: Trouver un objet avec une propriété dans un tablea .
Pour Swift 3,
let index = array.index(where: {$0.name == "foo"})
Utilisez Dollar qui est Lo-Dash ou Underscore.js pour Swift:
import Dollar
let found = $.find(array) { $0.name == "Foo" }
Par exemple, si nous avions un tableau de nombres:
let numbers = [2, 4, 6, 8, 9, 10]
Nous pourrions trouver le premier nombre impair comme ceci:
let firstOdd = numbers.index { $0 % 2 == 1 }
Cela renverra 4 comme un entier optionnel, car le premier nombre impair (9) est à l'index quatre.