web-dev-qa-db-fra.com

Filtre rapide tableau de chaînes

J'ai eu des problèmes pour filtrer un tableau de mots-clés (chaînes) dans Swift, Mon code:

self.filteredKeywords=filter(keywords.allValues, {(keyword:NSString) ->                                              
  Bool in
    let words=keyword as? NSString
    return words?.containsString(searchText)
  })

Comme AnyObject ne peut pas être un sous-type de NSString, je suis coincé avec ça!

9
Meseery

Swift 4.2 offre une nouvelle façon de procéder:

var theBigLebowski = ["The Dude", "Angry Walter", "Maude Lebowski", "Donny Kerabatsos", "The Big Lebowski", "Little Larry Sellers"]

// after removeAll -> ["The Dude", "Angry Walter", "Donny Kerabatsos", "Little Larry Sellers"]
theBigLebowski.removeAll{ $0.contains("Lebowski")}
print(theBigLebowski)
1
Adrian

[Mis à jour pour Swift 2.0]

Comme NSString est ponté sans frais vers Swift String, il suffit d'éviter les contraintes avec:

  3> ["abc", "bcd", "xyz"].filter() { nil != $0.rangeOfString("bc") }
$R1: [String] = 2 values {
  [0] = "abc"
  [1] = "bcd"
}

Mais si vous pensez que allValues ne sont pas des chaînes:

(keywords.allValues as? [String]).filter() { nil != $0.rangeOfString("bc") }

qui retourne un tableau optionnel.

16
GoZoner

Votre filter est terminé [AnyObject], mais votre fermeture prend NSString. Ceux-ci doivent correspondre. De plus, votre résultat doit être une Bool, pas un Bool?. Vous pouvez les adresser simplement comme ceci:

self.filteredKeywords = filter(keywords.allValues, {
    let keyword = $0 as? NSString
    return keyword?.containsString(searchText) ?? false
})

Ceci accepte AnyObject et essaie ensuite de le contraindre à NSString. Il nil-coalleces (??) ensuite le résultat pour s’assurer qu’il est toujours une Bool.

Je recommanderais cependant de traiter keywords comme un [String:String] plutôt que comme un NSDictionary. Cela éliminerait toutes les complications de AnyObject. Ensuite, vous pouvez simplement faire ceci:

self.filteredKeywords = keywords.values.filter { $0.rangeOfString(searchText) != nil }

Dans la mesure du possible, convertissez les collections Foundation en collections Swift dès que possible et stockez-les. Si vous avez des objets Foundation entrants, vous pouvez généralement les convertir facilement avec des techniques telles que:

let dict = nsdict as? [String:String] ?? [:]

Ou vous pouvez procéder comme suit pour les convertir de manière à ce qu'ils se bloquent lors du débogage (mais silencieusement, "fonctionnent" dans la version):

func failWith<T>(msg: String, value: T) -> T {
    assertionFailure(msg)
    return value
}

let dict = nsdict as? [String:String] ?? failWith("Couldn't convert \(d)", [:])
4
Rob Napier

La réponse de GoZoner pose un problème pour certains types de données et constitue un moyen légèrement meilleur de procéder. Les exemples suivants peuvent montrer ceci:

let animalArray: NSMutableArray = ["Dog","Cat","Otter","Deer","Rabbit"]
let filteredAnimals = animalArray.filter { $0.rangeOfString("er") != nil }
print("filteredAnimals:", filteredAnimals)

filteredAnimals: [Dog, Cat, Otter, Deer, Rabbit]

Probablement pas le jeu que vous attendiez!

Cependant, cela fonctionne bien de cette façon si nous ne tapons pas animalArray en tant que NSMutableArray :

let animalArray = ["Dog","Cat","Otter","Deer","Rabbit"]
let filteredAnimals = animalArray.filter { $0.rangeOfString("er") != nil }
print("filteredAnimals:", filteredAnimals)

filteredAnimals: [Otter, Deer]

Cependant, je recommanderais d'utiliser $ 0.contains () au lieu de $ 0.rangeOfString ()! = Nil car il fonctionne dans les deux cas et améliore légèrement la lisibilité du code:

let animalArray: NSMutableArray = ["Dog","Cat","Otter","Deer","Rabbit"]
let filteredAnimals = animalArray.filter { $0.contains("er") }
print("filteredAnimals:", filteredAnimals)

filteredAnimals: [Otter, Deer]
0
Ryan Davis