2010-06-19 21 views
48

¿Cómo buscar un NSSet o NSArray para un objeto que tiene un valor específico para una propiedad específica?¿Cómo buscar un NSSet o NSArray para un objeto que tiene un valor específico para una propiedad específica?

Ejemplo: Tengo un NSSet con 20 objetos y cada objeto tiene una propiedad type. Quiero obtener el primer objeto que tiene [theObject.type isEqualToString:@"standard"].

Recuerdo que era posible utilizar predicados de alguna manera para este tipo de cosas, ¿verdad?

Respuesta

76
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type == %@", @"standard"]; 
NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate]; 
id firstFoundObject = nil; 
firstFoundObject = filteredArray.count > 0 ? filteredArray.firstObject : nil; 

NB: La noción de la primera objeto encontrado en un NSSet no tiene sentido ya que el orden de los objetos en un conjunto no está definido.

+0

¿funciona si el objeto no tiene la propiedad de 'tipo', pero tiene otro objeto (digamos 'trabajo'), y este es 'trabajo' que tiene la propiedad 'tipo'? – darksider

+0

Sí, pero una clase debe ser código clave-clave que cumpla con las claves que desea usar en un predicado. –

+0

'indexOfObjectPassingTest' parece mejor por dos razones: (1) Utiliza un método real en lugar de * cadena * (2) Se detiene en el" primer "elemento que encuentra - no importa que un conjunto no esté ordenado, es posible que todavía desee un solo artículo. –

4
NSArray* results = [theFullArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.type LIKE[cd] %@", @"standard"]]; 
17

Usted puede obtener la matriz filtrada como Jason y Ole ha descrito, pero ya que lo que desea es un objeto, que haría uso de - indexOfObjectPassingTest: (si es en una matriz) o -objectPassingTest: (si es en un conjunto) y evitar la creación de la segundo conjunto.

+1

Parece una buena idea para un NSArray, pero el método en NSSet es en realidad '-objectsPassingTest:' (tenga en cuenta el plural), por lo que esta idea no es directamente posible allí, si entiendo esto correctamente. – Ashley

13

En general, uso indexOfObjectPassingTest: ya que me resulta más conveniente expresar mi prueba en código Objective-C que en la sintaxis NSPredicate. Aquí está un ejemplo simple (imaginemos que integerValue era en realidad una propiedad):

NSArray *array = @[@0,@1,@2,@3]; 
NSUInteger indexOfTwo = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { 
    return ([(NSNumber *)obj integerValue] == 2); 
}]; 
NSUInteger indexOfFour = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { 
    return ([(NSNumber *)obj integerValue] == 4); 
}]; 
BOOL hasTwo = (indexOfTwo != NSNotFound); 
BOOL hasFour = (indexOfFour != NSNotFound); 
NSLog(@"hasTwo: %@ (index was %d)", hasTwo ? @"YES" : @"NO", indexOfTwo); 
NSLog(@"hasFour: %@ (index was %d)", hasFour ? @"YES" : @"NO", indexOfFour); 

La salida de este código es:

hasTwo: YES (index was 2) 
hasFour: NO (index was 2147483647) 
Cuestiones relacionadas