web-dev-qa-db-fra.com

Trouver un objet dans un tableau?

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.

127
Sahat Yalkabov

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]
}
81
rintaro

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
}
232
Daniel

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]
}
119
user3799504

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é)

38
Brett

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
}
20
Muhammad Saifullah

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
}
18
Martin R

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]
}
8
Deokhyun Ko

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")
}
7
Pramod More

Swift

if yourArray.contains(item) {
   //item found, do what you want
}
else{
   //item not found 
   yourArray.append(item)
}
3
yonlau

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.

2
Yoichi Tagaya

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
1
George Filippakos

Un autre moyen d’accéder à array.index (of: Any) consiste à déclarer votre objet.

import Foundation
class Model: NSObject {  }
1
gabi doroftei

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 .

1
Christian Wörz

Pour Swift 3,

let index = array.index(where: {$0.name == "foo"})
1
Bali

Utilisez Dollar qui est Lo-Dash ou Underscore.js pour Swift:

import Dollar

let found = $.find(array) { $0.name == "Foo" }
1
Tyler Long

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.

0
Amul4608