2013-02-26 7 views
9

Wie konstruiere ich ein NSPredikat, das irgendwo in einem Array Objekte nach den Suchbegriffen sucht? Ich kann es nicht richtig erklären, also hier ist ein Beispiel.NSPredicate passt auf beliebige Zeichen

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" 
//) 

Aber wenn ich NSString *searchText = @"Test Str Appl"; verwenden bekomme ich null Ergebnisse. Ich möchte, dass es zu denselben Ergebnissen für diese Zeichenfolge passt.

Was ich suche ist eine Suchfunktion, die dem "Open Quickly" -Menü in Xcode ähnlich ist, wo es egal ist, ob Ihr Suchbegriff richtig formuliert ist, nur dass die Buchstaben in der richtigen Reihenfolge sind als ein Spiel. Ich hoffe wirklich, dass das Sinn ergibt.

Open Quickly Menu

+1

Offenbar der Begriff ich suchte war "Fuzzy Matching". – squarefrog

Antwort

19

Der LIKE String-Vergleich in Prädikate für Wildcards erlaubt * und ?, wo * Matches 0 oder mehr Zeichen. Deshalb, wenn Sie Ihren Suchtext in

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

durch ein * am Anfang Einfügen zwischen allen Charakteren verwandeln, und am Ende des ursprünglichen Suchtextes durch so etwas wie diese

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

mit dann Sie können verwenden

[NSPredicate predicateWithFormat:@"SELF LIKE[cd] %@", searchWithWildcards]; 

Das Prädikat sucht nach den Zeichen in der angegebenen Reihenfolge mit beliebigen anderen Zeichen zwischen ihnen.


Die Transformation kann beispielsweise mit dem folgenden Code erfolgen:

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

Genau das habe ich gesucht. Eine sehr elegante Lösung. Vielen Dank. – squarefrog

+0

@squarefrog: Gern geschehen. –