2013-02-26 11 views
9

Jak skonstruować NSPredicate, który szuka wyszukiwanych terminów w dowolnym miejscu obiektów Array? Nie mogę tego dokładnie wyjaśnić, więc oto przykład.NSPredicate pasuje do dowolnych znaków

NSArray *array = @[@"Test String: Apple", @"Test String: Pineapple", @"Test String: Banana"]; 
NSString *searchText = @"Apple"; 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", searchText]; 
NSArray *filteredArray = [array filteredArrayUsingPredicate:predicate]; 
NSLog(@"filteredArray: %@", filteredArray); 

// filteredArray: (
// "Test String: Apple", 
// "Test String: Pineapple" 
//) 

Ale jeśli użyję NSString *searchText = @"Test Str Appl";, otrzymam zero wyników. Chciałbym, żeby pasowało do tych samych wyników dla tego ciągu.

Czego szukam to funkcja wyszukiwania, która jest podobna do menu "Otwórz szybko" w Xcode, gdzie nie ma znaczenia, czy twój ciąg wyszukiwania jest poprawnie sformułowany, tylko że litery są we właściwej kolejności jako mecz. Naprawdę mam nadzieję, że ma to sens.

Open Quickly Menu

+1

Widocznie termin szukałem był „Fuzzy Matching”. – squarefrog

Odpowiedz

19

Porównanie LIKE ciąg w orzeczników pozwala na symbole wieloznaczne * i ?, gdzie * mecze 0 lub więcej znaków. Dlatego też, jeśli przekształcić tekst do wyszukania w

NSString *searchWithWildcards = @"*T*e*s*t* *S*t*r*A*p*p*l*"; 

wkładając * na początku, pomiędzy wszystkimi postaciami, a na końcu poszukiwanie oryginalnego tekstu za pomocą coś jak ten

NSMutableString *searchWithWildcards = [NSMutableString stringWithFormat:@"*%@*", self.searchField.text]; 
if (searchWithWildcards.length > 3) 
    for (int i = 2; i < self.searchField.text.length * 2; i += 2) 
     [searchWithWildcards insertString:@"*" atIndex:i]; 

następnie możesz użyć:

Predykat przeszukuje znaki w podanej kolejności, z dowolnymi innymi znakami między nimi.


Transformacja może na przykład być wykonane za pomocą następującego kodu:

NSMutableString *searchWithWildcards = [@"*" mutableCopy]; 
[searchText enumerateSubstringsInRange:NSMakeRange(0, [searchText length]) 
        options:NSStringEnumerationByComposedCharacterSequences 
       usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { 
        [searchWithWildcards appendString:substring]; 
        [searchWithWildcards appendString:@"*"]; 
       }]; 
+0

To jest dokładnie to, czego szukałem. Bardzo eleganckie rozwiązanie. Dziękuję Ci. – squarefrog

+0

@squarefrog: Nie ma za co. –