Utilizzando NSPredicate per filtrare un NSArray basata su chiavi NSDictionary
-
12-09-2019 - |
Domanda
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, ottengo alcun risultato. Penso che sto facendo qualcosa di sbagliato. So che questo è il metodo se "SPORT" è stato un Ivar. Penso che probabilmente è diverso se si tratta di una chiave.
Non sono stato in grado di trovare un esempio però.
Grazie
Aggiorna
ho aggiunto le virgolette attorno alla stringa che sto cercando.
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT == '%@')", @"Football"];
E 'ancora non funziona.
Aggiorna 2
Risolto esso. Ho dovuto togliere le virgolette singole, che sembra andare contro quello che dice la guida.
Il mio vero problema è che ho avuto un array nidificato e non ero in realtà la valutazione dei dizionari. osso testa di movimento.
Soluzione
Dovrebbe funzionare - fino a quando la variabile di dati è in realtà un array che contiene un dizionario con la chiave SPORT
NSArray *data = [NSArray arrayWithObject:[NSMutableDictionary dictionaryWithObject:@"foo" forKey:@"BAR"]];
NSArray *filtered = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(BAR == %@)", @"foo"]];
filtrata in questo caso contiene il dizionario.
(l'% @ non deve essere citato, questo viene fatto quando NSPredicate crea l'oggetto.)
Altri suggerimenti
Lo so che è una notizia vecchia, ma di aggiungere i miei due centesimi. Per impostazione predefinita, io uso i comandi LIKE[cd]
piuttosto che solo [c]
. Il [d]
confronta lettere con simboli di accento. Questo funziona bene soprattutto nel mio Warcraft App in cui la gente incantesimo il loro nome "voodoo" rendendo quasi impossibile per cercare il loro nome in un Tableview. Il [d]
strisce loro simboli accento durante il predicato. Quindi, un predicato di @"name LIKE[CD] %@", object.name
dove object.name == @"voodoo"
restituirà l'oggetto che contiene il nome del voodoo.
Dalla documentazione di Apple: come [cd] significa “maiuscole e diacritic-insensibile come”). Per una descrizione completa della sintassi di stringa e un elenco di tutti gli operatori disponibili, vedere Predicate Format String Sintassi .
#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
è disponibile solo in iPhone 3.0.
Non si dovrebbe notare che fino a cercare di eseguire sul dispositivo.
Con Swift 3, quando si desidera filtrare una serie di dizionari con un predicato in base a chiavi e valori del dizionario, è possibile scegliere uno dei seguenti modelli.
# 1. Utilizzando NSPredicate
init(format:arguments:)
inizializzazione
Se si proviene da Objective-C, init(format:arguments:)
offre uno stile di codifica di valori-chiave per valutare la vostra predicato.
Utilizzo:
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. Utilizzando NSPredicate
init(block:)
inizializzazione
In alternativa, se si preferisce fortemente tipizzato API oltre / API stringly digitati, è possibile utilizzare init(block:)
inizializzatore.
Utilizzo:
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"]]
Guardando il NSPredicate riferimento , sembra che tu abbia bisogno di circondare il vostro personaggio sostituzione con le citazioni. Ad esempio, il predicato corrente si legge: (SPORT == Football)
lo si vuole leggere (SPORT == 'Football')
, così il vostro stringa di formato deve essere @"(SPORT == '%@')"