2012-06-11 14 views
10

Tengo el siguiente NSArray contiene NSDictionary (s):Usando NSPredicate al filtro basado en varias claves (no los valores de clave)

NSArray *data = [[NSArray alloc] initWithObjects: 
       [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1], @"bill", [NSNumber numberWithInt:2], @"joe", nil], 
       [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:3], @"bill", [NSNumber numberWithInt:4], @"joe", [NSNumber numberWithInt:5], @"jenny", nil], 
       [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:6], @"joe", [NSNumber numberWithInt:1], @"jenny", nil], 
       nil]; 

Estoy queriendo crear un NSArray filtrada que sólo contiene objetos donde el NSDictionary coincide con múltiples 'claves' usando NSPredicate.

Por ejemplo:

  • filtro de la matriz para contener solamente los objetos NSDictionary que tienen claves "Bill" y "Joe" [resultado deseado: nuevo NSArray contendría el primeros dos objetos NSDictionary]
  • filtro de la matriz para contener solamente los objetos NSDictionary que tienen claves "Joe" y "Jenny" [resultado deseado: nuevo NSArray contendría los últimos dos objetos NSDictionary]

¿Puede alguien explicar el formato de NSPredicate para lograr esto?

Editar: puedo lograr un resultado similar al NSPredicate deseada usando:

NSMutableArray *filteredSet = [[NSMutableArray alloc] initWithCapacity:[data count]]; 
NSString *keySearch1 = [NSString stringWithString:@"bill"]; 
NSString *keySearch2 = [NSString stringWithString:@"joe"]; 

for (NSDictionary *currentDict in data){ 
    // objectForKey will return nil if a key doesn't exists. 
    if ([currentDict objectForKey:keySearch1] && [currentDict objectForKey:keySearch2]){ 
     [filteredSet addObject:currentDict]; 
    } 
} 

NSLog(@"filteredSet: %@", filteredSet); 

estoy imaginando NSPredicate sería más elegante si es que existe?

Respuesta

24

la única forma que sé es combinar dos condiciones como " 'valor1' en la lista Y 'valor2' en la lista de"

auto. @ AllKeys deben devolver todas las claves del diccionario (auto es cada diccionario en su matriz). Si no se escribe con el prefijo @ entonces el diccionario será sólo tiene que buscar una llave que es "AllKeys" en lugar del método "- (NSArray *) AllKeys"

El código:

NSArray* billAndJoe = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%@ IN [email protected] AND %@ IN [email protected]" , @"bill",@"joe" ]]; 


NSArray* joeAndJenny = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%@ IN [email protected] AND %@ IN [email protected]" , @"joe",@"jenny" ]] 
+0

También podría usar NSCompoundPredicate's '+ andPredicateWithSubpredicates:' en lugar de hardcoding solo 2 opciones. –

+0

Gracias. Voy a intentar esto por la mañana. ¡Aunque el código se parece a lo que quiero! –

+0

Ok ... finalmente volví a esto. El código funciona, solo necesita asegurarse de que es aloac init-ed: 'NSArray * billAndJoe = [[NSArray alloc] initWithArray: [NSArray arrayWithArray: [data filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"% @ IN self. @ AllKeys AND% @ IN self. @ AllKeys ", @" bill ", @" joe "]]]]' –

5

Dado que un diccionario simplemente devuelve nil si solicita un valor de una clave no existente, basta con especificar que el valor debe ser no nulo. Un formato como el siguiente debe cubrir su primer caso:

[NSPredicate predicateWithFormat: @"%K != nil AND %K != nil", @"bill", @"joe"] 

El segundo caso, con "Joe" y "Jenny" sigue un patrón similar, por supuesto.

Cuestiones relacionadas