Utilizzo di NSPredicate per filtrare un NSArray basato su chiavi NSDictionary

Ho una serie di dizionari.

Voglio filtrare l’array in base a una chiave.

Ho provato questo:

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

Questo non funziona, non ottengo risultati. Penso di fare qualcosa di sbagliato. So che questo è il metodo se “SPORT” era un ivar. Penso che sia probabilmente diverso se è una chiave.

Tuttavia, non sono stato in grado di trovare un esempio.

Grazie


Aggiornare

Ho aggiunto citazioni sulla stringa che sto cercando.

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

Ancora non funziona.


Aggiornamento 2

Risolto. In realtà ho dovuto rimuovere le virgolette singole, che sembrano andare contro ciò che dice la guida.

Il mio vero problema è che avevo un array annidato e in realtà non stavo valutando i dizionari. Mossa della testa d’osso.

Dovrebbe funzionare – purché la variabile dati sia in realtà una matrice contenente un dizionario con la chiave SPORT

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

Filtrato in questo caso contiene il dizionario.

(% @ non deve essere quotato, questo viene fatto quando NSPredicate crea l’object.)

So che sono vecchie notizie ma per aggiungere i miei due centesimi. Di default uso i comandi LIKE[cd] piuttosto che solo [c] . [d] confronta le lettere con i simboli di accento. Questo funziona particolarmente bene nella mia app di Warcraft in cui le persone scrivono il loro nome “Vòódòó” rendendo quasi imansible cercare il loro nome in una tabella. [d] elimina i loro simboli di accento durante il predicato. Quindi un predicato di @"name LIKE[CD] %@", object.name dove object.name == @"voodoo" restituirà l’object che contiene il nome Vòódòó.

Dalla documentazione di Apple: come [cd] significa “case- e diacritic-insensitive come.”) Per una descrizione completa della syntax delle stringhe e un elenco di tutti gli operatori disponibili, vedere Sintassi delle stringhe di Predicate Format .

 #import  // 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 è disponibile solo in iPhone 3.0.

Non lo noterai prima di provare a eseguire il dispositivo.

Con Swift 3, quando si desidera filtrare una matrice di dizionari con un predicato basato su chiavi e valori del dizionario, è ansible scegliere uno dei seguenti modelli.


# 1. Utilizzo NSPredicate init(format:arguments:) NSPredicate

Se vieni da Objective-C, init(format:arguments:) offre uno stile di codifica a valori-chiave per valutare il tuo predicato.

Uso:

 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. Utilizzo NSPredicate init(block:) NSPredicate

In alternativa, se si preferiscono le API fortemente tipizzate su API con stringhe tipizzate , è ansible utilizzare init(block:) initializer.

Uso:

 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"]] 

Osservando il riferimento NSPredicate , sembra che tu debba circondare il tuo carattere di sostituzione con le virgolette. Ad esempio, il tuo attuale predicato riporta: (SPORT == Football) Vuoi leggerlo (SPORT == 'Football') , quindi la stringa di formato deve essere @"(SPORT == '%@')" .