Dans Swift, comment puis-je vérifier si un élément existe dans un tableau? Xcode n'a aucune suggestion pour contain
, include
ou has
, et une recherche rapide dans le livre n'a révélé aucun résultat. Une idée de comment vérifier cela? Je sais qu'il existe une méthode find
qui renvoie le numéro d'index, mais existe-t-il une méthode qui renvoie un booléen tel que #include?
de Ruby?
Exemple de ce dont j'ai besoin:
var elements = [1,2,3,4,5]
if elements.contains(5) {
//do something
}
Swift 2, 3, 4, 5:
let elements = [1, 2, 3, 4, 5]
if elements.contains(5) {
print("yes")
}
contains()
est une méthode d'extension de protocole de SequenceType
(pour les séquences d'éléments Equatable
) et non une méthode globale comme dans les versions précédentes.
Remarques:
contains()
nécessite que les éléments de séquence adoptent le protocole Equatable
, comparez par exemple. réponse d'Andrews .NSObject
, vous devez remplacer isEqual:
, voir sous-classe NSObject dans Swift: hash vs hashValue, isEqual vs == .contains()
qui n'exige pas que les éléments soient équivalents et prend un prédicat comme argument, voir p. Ex. Raccourci pour tester si un objet existe dans un tableau pour Swift? .Swift anciennes versions:
let elements = [1,2,3,4,5]
if contains(elements, 5) {
println("yes")
}
Pour ceux qui sont venus ici à la recherche d'une recherche et suppriment un objet d'un tableau:
Swift 1
if let index = find(itemList, item) {
itemList.removeAtIndex(index)
}
Swift 2
if let index = itemList.indexOf(item) {
itemList.removeAtIndex(index)
}
Swift 3, 4, 5
if let index = itemList.index(of: item) {
itemList.remove(at: index)
}
Utilisez cette extension:
extension Array {
func contains<T where T : Equatable>(obj: T) -> Bool {
return self.filter({$0 as? T == obj}).count > 0
}
}
Utilisé comme:
array.contains(1)
Mise à jour pour Swift 2/
Notez qu'à partir de Swift 3 (ou même 2), l'extension n'est plus nécessaire car la fonction globale contains
a été transformée en une paire de méthodes d'extension sur Array
, qui vous permettent de faire l'un des:
let a = [ 1, 2, 3, 4 ]
a.contains(2) // => true, only usable if Element : Equatable
a.contains { $0 < 1 } // => false
Si vous vérifiez si une instance d'un classe ou structure personnalisée est contenue dans un tableau, vous devez implémenter le protocole Équable avant de pouvoir utiliser .contains (myObject ).
Par exemple:
struct Cup: Equatable {
let filled:Bool
}
static func ==(lhs:Cup, rhs:Cup) -> Bool { // Implement Equatable
return lhs.filled == rhs.filled
}
alors vous pouvez faire:
cupArray.contains(myCup)
Astuce: le remplacement de == devrait se faire au niveau global, pas dans votre classe/structure
J'ai utilisé le filtre.
let results = elements.filter { el in el == 5 }
if results.count > 0 {
// any matching items are in results
} else {
// not found
}
Si vous voulez, vous pouvez compresser cela pour
if elements.filter({ el in el == 5 }).count > 0 {
}
J'espère que ça t'as aidé.
Mise à jour pour Swift 2
Vive les implémentations par défaut!
if elements.contains(5) {
// any matching items are in results
} else {
// not found
}
(Swift 3)
Si l'intention est:
Ensuite, une alternative à contains(_:)
comme Sequence
est définie sur first(where:)
sur Sequence
:
let elements = [1, 2, 3, 4, 5]
if let firstSuchElement = elements.first(where: { $0 == 4 }) {
print(firstSuchElement) // 4
// ...
}
Dans cet exemple artificiel, son utilisation peut sembler absurde, mais elle est très utile pour interroger des tableaux de types d'éléments non fondamentaux afin de déterminer l'existence d'éléments remplissant certaines conditions. Par exemple.
struct Person {
let age: Int
let name: String
init(_ age: Int, _ name: String) {
self.age = age
self.name = name
}
}
let persons = [Person(17, "Fred"), Person(16, "Susan"),
Person(19, "Hannah"), Person(18, "Sarah"),
Person(23, "Sam"), Person(18, "Jane")]
if let eligableDriver = persons.first(where: { $0.age >= 18 }) {
print("\(eligableDriver.name) can possibly drive the rental car in Sweden.")
// ...
} // Hannah can possibly drive the rental car in Sweden.
let daniel = Person(18, "Daniel")
if let sameAgeAsDaniel = persons.first(where: { $0.age == daniel.age }) {
print("\(sameAgeAsDaniel.name) is the same age as \(daniel.name).")
// ...
} // Sarah is the same age as Daniel.
Toute opération chaînée utilisant .filter { ... some condition }.first
peut être remplacée favorablement par first(where:)
. Ce dernier montre une meilleure intention et offre des avantages en termes de performances par rapport aux possibles appliances non-paresseuses de .filter
, car celles-ci transmettent l'ensemble du tableau avant l'extraction du premier (possible) premier élément transmettant le filtre.
Un commentaire sous les requêtes:
Comment puis-je supprimer le
firstSuchElement
du tableau?
Un cas d'utilisation similaire à celui ci-dessus consiste à supprimer le premier élément qui remplit un prédicat donné. Pour ce faire, la méthode index(where:)
de Collection
(facilement disponible pour la collection de tableaux) peut être utilisée pour trouver l'index du premier élément remplissant le prédicat, après quoi l'index peut être utilisé avec la méthode remove(at:)
de Array
pour (possible; étant donné qu’elle existe), supprimer cet élément.
var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]
if let indexOfFirstSuchElement = elements.index(where: { $0 == "c" }) {
elements.remove(at: indexOfFirstSuchElement)
print(elements) // ["a", "b", "d", "e", "a", "b", "c"]
}
Ou, si vous souhaitez supprimer l'élément du tableau et travailler avec , appliquez la méthode Optional
: s map(_:)
à conditionnellement (pour .some(...)
, retour de index(where:)
), utilisez le résultat de index(where:)
pour supprimer et capturer l'élément supprimé du tableau (dans une clause de liaison facultative).
var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]
if let firstSuchElement = elements.index(where: { $0 == "c" })
.map({ elements.remove(at: $0) }) {
// if we enter here, the first such element have now been
// remove from the array
print(elements) // ["a", "b", "d", "e", "a", "b", "c"]
// and we may work with it
print(firstSuchElement) // c
}
Notez que dans l'exemple ci-dessus, les membres du tableau sont de simples types de valeur (instances String
). L'utilisation d'un prédicat pour trouver un membre donné est donc un peu trop lourde, car nous pourrions simplement tester l'égalité en utilisant la méthode plus simple index(of:)
, comme indiqué dans - Réponse de @ DogCoffee . Cependant, si vous appliquez la méthode de recherche/suppression ci-dessus à l'exemple Person
, il est approprié d'utiliser index(where:)
avec un prédicat (car nous ne testons plus l'égalité, mais le respect d'un prédicat fourni).
Le moyen le plus simple d'y parvenir est d'utiliser un filtre sur le tableau.
let result = elements.filter { $0==5 }
result
aura l'élément trouvé s'il existe et sera vide si l'élément n'existe pas. Donc, vérifier simplement si result
est vide vous dira si l'élément existe dans le tableau. Je voudrais utiliser les éléments suivants:
if result.isEmpty {
// element does not exist in array
} else {
// element exists
}
À partir de Swift 2.1, les NSArrays ont containsObject
qui peut être utilisé comme suit:
if myArray.containsObject(objectImCheckingFor){
//myArray has the objectImCheckingFor
}
Juste au cas où quelqu'un essaierait de trouver si une indexPath
fait partie des fonctions sélectionnées (comme dans un UICollectionView
ou UITableView
cellForItemAtIndexPath
fonctions):
var isSelectedItem = false
if let selectedIndexPaths = collectionView.indexPathsForSelectedItems() as? [NSIndexPath]{
if contains(selectedIndexPaths, indexPath) {
isSelectedItem = true
}
}
Voici ma petite extension que je viens d'écrire pour vérifier si mon tableau de délégués contient un objet délégué ou non (Swift 2). :) Il fonctionne également avec les types de valeur comme un charme.
extension Array
{
func containsObject(object: Any) -> Bool
{
if let anObject: AnyObject = object as? AnyObject
{
for obj in self
{
if let anObj: AnyObject = obj as? AnyObject
{
if anObj === anObject { return true }
}
}
}
return false
}
}
Si vous avez une idée sur la façon d'optimiser ce code, faites-le moi savoir.
Swift 4, une autre façon d'y parvenir, avec la fonction de filtrage
var elements = [1,2,3,4,5]
if let object = elements.filter({ $0 == 5 }).first {
print("found")
} else {
print("not found")
}
let elements = [1, 2, 3, 4, 5, 5]
elements.contains(5) // true
elements.firstIndex(of: 5) // 4
elements.firstIndex(of: 10) // nil
let results = elements.filter { element in element == 5 }
results.count // 2
si l'utilisateur trouve des éléments de tableau particuliers, utilisez le code ci-dessous identique à la valeur entière.
var arrelemnts = ["sachin", "test", "test1", "test3"]
if arrelemnts.contains("test"){
print("found") }else{
print("not found") }
Swift
Si vous n'utilisez pas d'objet, vous pouvez utiliser ce code pour contient.
let elements = [ 10, 20, 30, 40, 50]
if elements.contains(50) {
print("true")
}
Si vous utilisez NSObject Class dans Swift. Cette variable est en fonction de mes besoins. vous pouvez modifier pour votre exigence.
var cliectScreenList = [ATModelLeadInfo]()
var cliectScreenSelectedObject: ATModelLeadInfo!
Ceci est pour un même type de données.
{ $0.user_id == cliectScreenSelectedObject.user_id }
Si vous voulez tout type AnyObject.
{ "\($0.user_id)" == "\(cliectScreenSelectedObject.user_id)" }
État complet
if cliectScreenSelected.contains( { $0.user_id == cliectScreenSelectedObject.user_id } ) == false {
cliectScreenSelected.append(cliectScreenSelectedObject)
print("Object Added")
} else {
print("Object already exists")
}
qu'en est-il d'utiliser une table de hachage pour le travail, comme celui-ci?
tout d'abord, créer une fonction générique "hash map", étendant le protocole de séquence.
extension Sequence where Element: Hashable {
func hashMap() -> [Element: Int] {
var dict: [Element: Int] = [:]
for (i, value) in self.enumerated() {
dict[value] = i
}
return dict
}
}
Cette extension fonctionnera aussi longtemps que les éléments du tableau seront conformes à Hashable, comme des entiers ou des chaînes, voici l'utilisation ...
let numbers = Array(0...50)
let hashMappedNumbers = numbers.hashMap()
let numToDetect = 35
let indexOfnumToDetect = hashMappedNumbers[numToDetect] // returns the index of the item and if all the elements in the array are different, it will work to get the index of the object!
print(indexOfnumToDetect) // prints 35
Mais pour l'instant, concentrons-nous pour vérifier si l'élément est dans le tableau.
let numExists = indexOfnumToDetect != nil // if the key does not exist
means the number is not contained in the collection.
print(numExists) // prints true
Swift 4.2 +
Vous pouvez facilement vérifier que votre instance est un tableau ou non à l’aide de la fonction suivante.
func verifyIsObjectOfAnArray<T>(_ object: T) -> Bool {
if let _ = object as? [T] {
return true
}
return false
} .
Même vous pouvez y accéder comme suit. Vous recevrez Nil
si l'objet ne serait pas un tableau.
func verifyIsObjectOfAnArray<T>(_ object: T) -> [T]? {
if let array = object as? [T] {
return array
}
return nil
}