web-dev-qa-db-fra.com

Utilisation de NSPredicate pour filtrer un tableau NSArray basé sur des clés NSDictionary

J'ai un tableau de dictionnaires.

Je veux filtrer le tableau basé sur une clé.

J'ai essayé ceci:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT ==  %@)", @"Football"];

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

Cela ne fonctionne pas, je n'obtiens aucun résultat. Je pense que je fais quelque chose de mal. Je sais que c'est la méthode si "SPORT" était un ivar. Je pense que c'est probablement différent si c'est une clé.

Je n'ai pas été capable de trouver un exemple cependant.

Merci


Mettre à jour

J'ai ajouté des guillemets autour de la chaîne que je cherche.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT ==  '%@')", @"Football"];

Cela ne fonctionne toujours pas.


Mise à jour 2

Résolu. En fait, j'ai dû supprimer les guillemets simples, ce qui semble aller à l'encontre des indications du guide.

Mon vrai problème est que j'avais un tableau imbriqué et que je n'évaluais pas réellement les dictionnaires. La tête des os bouge.

94
Corey Floyd

Cela devrait fonctionner - tant que la variable de données est en réalité un tableau contenant un dictionnaire avec la clé SPORT

NSArray *data = [NSArray arrayWithObject:[NSMutableDictionary dictionaryWithObject:@"foo" forKey:@"BAR"]];    
NSArray *filtered = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(BAR == %@)", @"foo"]];

Filtré dans ce cas contient le dictionnaire. 

(Le% @ ne doit pas nécessairement être cité, cela est fait lorsque NSPredicate crée l'objet.)

150
suraken

Je sais que c'est de vieilles nouvelles, mais pour ajouter mes deux cents. Par défaut, j'utilise les commandes LIKE[cd] plutôt que simplement [c]. Le [d] compare les lettres avec des symboles accentués. Cela fonctionne particulièrement bien dans mon application Warcraft où les gens épellent leur nom "Vòódòó", ce qui rend presque impossible la recherche de leur nom dans une table. Le [d] supprime leurs symboles d’accent lors du prédicat. Donc, un prédicat de @"name LIKE[CD] %@", object.nameobject.name == @"voodoo" retournera l'objet contenant le nom Vòódòó.

Dans la documentation Apple: Like [cd] signifie "insensible à la casse et aux signes diacritiques, comme.") Pour obtenir une description complète de la syntaxe de chaîne et une liste de tous les opérateurs disponibles, voir PREDICATE FORMAT STRING SYNTAX .

27
ChargedNeuron
#import <Foundation/Foundation.h>
// clang -framework Foundation Siegfried.m 
    int
main() {
    NSArray *arr = @[
        @{@"1" : @"Fafner"},
        @{@"1" : @"Fasolt"}
    ];
    NSPredicate *p = [NSPredicate predicateWithFormat:
        @"SELF['1'] CONTAINS 'e'"];
    NSArray *res = [arr filteredArrayUsingPredicate:p];
    NSLog(@"Siegfried %@", res);
    return 0;
}

NSPredicate est uniquement disponible sur iPhone 3.0. 

Vous ne le remarquerez pas avant d'essayer de fonctionner sur le périphérique.

3
Rod

Avec Swift 3, lorsque vous souhaitez filtrer un tableau de dictionnaires avec un prédicat basé sur des clés et des valeurs de dictionnaire, vous pouvez choisir l'un des modèles suivants.


#1. Utilisation de NSPredicateinit(format:arguments:) initializer

Si vous venez d'Objective-C, init(format:arguments:) offre un style de codage valeur-clé pour évaluer votre prédicat.

Usage:

import Foundation

let array = [["key1": "value1", "key2": "value2"], ["key1": "value3"], ["key3": "value4"]]

let predicate = NSPredicate(format: "key1 == %@", "value1")
//let predicate = NSPredicate(format: "self['key1'] == %@", "value1") // also works
let filteredArray = array.filter(predicate.evaluate)

print(filteredArray) // prints: [["key2": "value2", "key1": "value1"]]

# 2. Utilisation de NSPredicateinit(block:) initializer

Si vous préférez les API fortement typées par rapport aux API fortement typées, vous pouvez utiliser l'initialiseur init(block:).

Usage:

import Foundation

let array = [["key1": "value1", "key2": "value2"], ["key1": "value3"], ["key3": "value4"]]

let dictPredicate = NSPredicate(block: { (obj, _) in
    guard let dict = obj as? [String: String], let value = dict["key1"] else { return false }
    return value == "value1"
})

let filteredArray = array.filter(dictPredicate.evaluate)
print(filteredArray) // prints: [["key2": "value2", "key1": "value1"]]
0
Imanou Petit