Usar NSPredicate para filtrar un NSArray basado en claves NSDictionary

Tengo una variedad de diccionarios.

Quiero filtrar la matriz en función de una clave.

Intenté esto:

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

Esto no funciona, no obtengo resultados. Creo que estoy haciendo algo mal. Sé que este es el método si “DEPORTE” fue un ivar. Creo que probablemente sea diferente si es una clave.

Sin embargo, no he podido encontrar un ejemplo.

Gracias


Actualizar

Agregué comillas alrededor de la cadena que estoy buscando.

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

Todavía no funciona.


Actualización 2

Resuelto. De hecho, tuve que eliminar las comillas simples, lo que parece ir en contra de lo que dice la guía.

Mi verdadero problema es que tenía una matriz anidada y en realidad no estaba evaluando los diccionarios. Movimiento de la cabeza del hueso

Debería funcionar, siempre que la variable de datos sea en realidad una matriz que contenga un diccionario con la clave SPORT.

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

Filtrado en este caso contiene el diccionario.

(el% @ no tiene que ser citado, esto se hace cuando NSPredicate crea el objeto.)

Sé que son viejas noticias, pero para agregar mis dos centavos. Por defecto, uso los comandos LIKE[cd] lugar de solo [c] . El [d] compara letras con símbolos de acento. Esto funciona especialmente bien en mi aplicación Warcraft donde las personas deletrean su nombre “Vòódòó”, lo que hace que sea casi imposible buscar su nombre en una tabla. El [d] quita sus símbolos de acento durante el predicado. Entonces, un predicado de @"name LIKE[CD] %@", object.name donde object.name == @"voodoo" devolverá el objeto que contiene el nombre Vòódòó.

De la documentación de Apple: como [cd] significa “insensible a las mayúsculas y a las diacríticas”. Para obtener una descripción completa de la syntax de la cadena y una lista de todos los operadores disponibles, vea Predicate la syntax de la cadena de formato .

 #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 solo está disponible en iPhone 3.0.

No lo notarás hasta que intentes ejecutarlo en el dispositivo.

Con Swift 3, cuando desee filtrar una matriz de diccionarios con un predicado basado en las claves y valores del diccionario, puede elegir uno de los siguientes patrones.


# 1. Usando NSPredicate init(format:arguments:) inicializador

Si proviene de Objective-C, init(format:arguments:) ofrece un estilo de encoding de clave-valor para evaluar su predicado.

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

Como alternativa, si prefiere las API fuertemente tipadas sobre las API de tipo stringly , puede utilizar 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"]] 

Mirando la referencia NSPredicate , parece que necesita rodear su personaje de sustitución con comillas. Por ejemplo, su predicado actual dice: (SPORT == Football) Desea que lea (SPORT == 'Football') , por lo que su cadena de formato debe ser @"(SPORT == '%@')" .