2011-08-29 13 views
15

Chciałbym wiedzieć, jak odzyskać indeks NSArray przy użyciu NSPredicate?Jak odzyskać indeks NSArray za pomocą NSPredicate?

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

Wich rodzaju metody należy użyć, aby uzyskać indeks „Los Angles”, dając jedynie NSString
Uwaga: @"Los An" lub @"geles" powinien wrócić tego samego indeksu ..

Odpowiedz

20

Korzystanie NSPredicate ty można dostać tablicę ciągów, które zawierają szukania ciąg (wydaje się, że nie ma wbudowanej metody, aby tylko indeksy element):

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

można uzyskać tylko za pomocą indeksów indexesOfObjectsPassingTest: meto 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; 
}]; 

Jeśli chcesz uzyskać tylko jeden element zawierający swój ciąg można użyć podobnej metody indexOfObjectPassingTest: za to.

+0

mówi range.origin nie istnieje ... – wagashi

+0

@wagashi, uh, dzięki, niewłaściwa nazwa nieruchomości. Zabawne, że pierwszy zauważyłeś błąd - po 7 miesiącu :) – Vladimir

+0

:) Przy okazji, powinno być "^ BOOL (id obj, NSUInteger idx, BOOL * stop)" – wagashi

21

Powinieneś być w stanie to zrobić za pomocą bloków. Poniżej znajduje się fragment (nie mam kompilatora poręczny więc pls usprawiedliwiać żadnych literówek):

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]; 
        }]; 

Zasadniczo można użyć indexOfObjectPassingTest: metoda. To zajmuje blok (kod następujący po "^") i zwraca indeks pierwszego obiektu, który pasuje do twojego predykatu (lub NSNotFound, jeśli nie istnieje dopasowanie). Blok przechodzi przez każdy obiekt w tablicy aż do znalezienia dopasowania (w którym momencie zwraca indeks) lub nie znaleziono żadnego dopasowania (w którym momencie zwraca NSNotFound). Tu jest link do blokowania programowania, które mogą pomóc zrozumieć logikę w bloku:

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

+0

Świetna odpowiedź dziękuję –

1

chciałbym to zrobić ..

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

pozwól mi zrobić kilka uwag: 1) jeśli nie ma elementu pasującego do napisu, twój foundInIndex pozostanie niezainicjowany i nie będziesz mógł go użyć. 2) możesz uzyskać lepszą wydajność przy użyciu szybkiego wyliczenia lub wyliczenia blokowego 3) nie ma sensu używać - opis metody tutaj 4) należy pamiętać, że twój kod znajdzie ostatni element w tablicy, który zawiera ciąg wyszukiwania – Vladimir

3

Znaleziono alternatywne podejście pomocny gdzie wyszukiwanie jest bardziej złożony, ponieważ pozwala na użycie predykatu do znalezienia obiektu, następnie obiekt do znalezienia indeksu:

-(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

Na podstawie odpowiedzi @Louie, zamiast używać do w pętli użyłem bloku wyliczeniowego, który zadziałał dla mnie.

Zrobiłem to: -

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

Rozwiązanie Vladimir wydaje się bardziej proste do znalezienia indeksów niż to. – klefevre

Powiązane problemy