2013-02-26 79 views
9

如何构造一个NSPredicate,在数组对象中的任何位置查找搜索项?我不能很好地解释它,所以这里是一个例子。NSPredicate与任何字符匹配

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

但是,如果我使用NSString *searchText = @"Test Str Appl";我得到零结果。我希望它匹配这个字符串的相同结果。

我在寻找的是一个搜索功能,它类似于Xcode中的“打开快速”菜单,它不关心你的搜索字符串的措辞是否正确,只是字母的顺序是正确的作为比赛。我真的希望这是有道理的。

Open Quickly Menu

+1

很显然,我一直在寻找的术语是“模糊匹配”。 – squarefrog 2013-02-26 14:20:29

回答

19

在谓词的LIKE字符串比较允许通配符*?,其中*匹配0或多个字符。因此,如果使用这样的事情

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

然后将您的搜索文本

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

通过插入*之初,所有字符之间,并在原始搜索文本的结尾你可以在给定的顺序使用

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

谓词搜索字符,它们之间的任意其它字符。


转型例如可以用下面的代码来完成:

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

这正是我一直在寻找的。非常优雅的解决方案。谢谢。 – squarefrog 2013-02-26 14:40:16

+0

@squarefrog:不客气。 – 2013-02-26 14:45:30