2011-08-29 16 views
15

¿Sabría cómo recuperar un índice de NSArray usando un NSPredicate?¿Cómo recuperar un índice de un NSArray utilizando un NSPredicate?

NSArray *array = [NSArray arrayWithObjects: 
        @"New-York City", 
        @"Washington DC", 
        @"Los Angeles", 
        @"Detroit", 
        nil]; 

Wich tipo de método se debe utilizar con el fin de obtener el índice de "Los Ángeles" por dar sólo un NSString
NB: @"Los An" o @"geles" debe devolver el mismo índice ..

Respuesta

20

Usando NSPredicate se puede obtener matriz de cadenas que contengan la cadena de búsqueda (parece que no hay método integrado para obtener índices de elementos sólo):

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", searchString]; 
NSArray *filteredArray = [array filteredArrayUsingPredicate: predicate]; 

, usted puede obtener un índice solamente usando indexesOfObjectsPassingTest: metho d:

NSIndexSet *indexes = [array indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){ 
    NSString *s = (NSString*)obj; 
    NSRange range = [s rangeOfString: searchString]; 
    return range.location != NSNotFound; 
}]; 

Si desea obtener sólo un elemento que contiene la cadena se puede utilizar el método indexOfObjectPassingTest: similares para eso.

+0

dice range.origin no existe ... – wagashi

+0

@wagashi, uh, gracias, nombre de la propiedad equivocada. Es curioso que eres el primero en detectar un error - después de 7 meses :) – Vladimir

+0

:) Por cierto, debería ser "^ BOOL (id obj, NSUInteger idx, BOOL * detener)" – wagashi

21

Debería poder hacer esto con bloques. A continuación se muestra un fragmento (no tengo un compilador mano así que por favor disculpe las posibles erratas):

NSArray *array = [NSArray arrayWithObjects: 
       @"New-York City", 
       @"Washington DC", 
       @"Los Angeles", 
       @"Detroit", 
       nil]; 
NSString *matchCity = @"Los"; 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", matchCity]; 
NSUInteger index = [self.array indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) { 
           return [predicate evaluateWithObject:obj]; 
        }]; 

Esencialmente, usted puede utilizar el indexOfObjectPassingTest: método. Esto toma un bloque (código que sigue al "^") y devuelve el índice para el primer objeto que coincide con su predicado (o NSNotFound si no existe una coincidencia). El bloque itera a través de cada objeto en la matriz hasta que se encuentra una coincidencia (en cuyo punto se devuelve el índice) o no se encuentra ninguna coincidencia (en cuyo punto se devuelve NSNotFound). Aquí hay un enlace para bloquear la programación que puede ayudar a entender la lógica dentro del bloque:

https://developer.apple.com/library/ios/featuredarticles/Short_Practical_Guide_Blocks/

+0

Gran respuesta gracias –

1

Me gustaría hacer esto ..

NSString * stringToCompare = @"geles"; 
int foundInIndex; 

for (int i=0; i<[array count]; i++){ 

    NSString * tryString = [[array objectAtIndex:i] description]; 

    if ([tryString rangeOfString:stringToCompare].location == NSNotFound) { 
     // no match 
    } else { 
     //match found 
     foundInIndex = i; 
    } 



}// end for loop 
+0

déjame hacer algunos comentarios: 1) si no hay ningún elemento que coincida con la cadena, su foundInIndex permanecerá sin inicializar y no podrá usarlo. 2) puede obtener un mejor rendimiento usando la enumeración rápida o la enumeración basada en bloques 3) no tiene sentido usar el método de descripción aquí 4) tenga en cuenta que su código encontrará el último elemento en la matriz que contiene la cadena de búsqueda – Vladimir

3

Encontró un enfoque alternativo útil donde la búsqueda es más complejo ya que permite predicado a ser usado para encontrar el objeto a continuación, objeto de encontrar index:

-(NSIndexPath*) indexPathForSelectedCountry{ 
    NSUInteger indexToCountry = 0; 
    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isoCode = %@",self.selectedCountry.isoCode]; 
    NSArray * selectedObject = [self.countryList filteredArrayUsingPredicate:predicate]; 
    if (selectedObject){ 
     if (self.searchDisplayController.isActive){ 
      indexToCountry = [self.searchResults indexOfObject:selectedObject[0]]; 
     }else{ 
      indexToCountry = [self.countryList indexOfObject:selectedObject[0]]; 
     } 
    } 
    return [NSIndexPath indexPathForRow:indexToCountry inSection:0]; 
} 
0

Basado en respuesta @Louie, en lugar de utilizar para Yo había usado el bloque de enumeración que funcionó para mí.

lo hice: -

NSString *stringToCompare = @"xyz"; 

[myArray enumerateObjectsUsingBlock:^(id *Obj, NSUInteger idx, BOOL * _Nonnull stop) { 
NSString * tryString = [[myArray objectAtIndex:idx] description]; 

    if ([tryString rangeOfString:stringToCompare].location == NSNotFound) { 

       // no match found 

     } else { 

       //match found and perform your operation. In my case i had removed array object at idx 

      } 
     }]; 
+0

La solución de Vladimir parece más sencillo para encontrar índices que esto. – klefevre

Cuestiones relacionadas