Objective-C - 比NSCaseInsensitiveSearch更好的搜索?关键词? NSPredicate?

时间:2013-08-05 11:40:18

标签: iphone ios search plist nspredicate

目前我正在使用它来搜索我的字典数组(来自plist文件):

for(NSDictionary *wine in mainArray)
    {
        NSString *wineName = [wine objectForKey:@"name"];
        NSRange range = [wineName rangeOfString:searchText options:NSCaseInsensitiveSearch];
        if(range.location != NSNotFound)
            [searchArray addObject:wine];
    }

在这个问题中,我将把这个plist作为一个例子:

<array>
<dict>
  <key>name</key>
  <string>Banana One (Yellow)</string>
  <key>value</key>
  <string>1</string>
</dict>
<dict>
  <key>name</key>
  <string>Apple Two (White)</string>
  <key>value</key>
  <string>2</string>
</dict>
<dict>
  <key>name</key>
  <string>Pineapple Three (Orange)</string>
  <key>value</key>
  <string>3</string>
</dict>
<dict>
</array>

(不关心价值)

好的,当我使用带有NSCaseInsensitiveSearch的UISearchBar时,我可以直接搜索数组(ObjectForKey=@"name"),而无需考虑Case。好!

例如我可以搜索:@"banana"并找到:Banana One(黄色)

我可以搜索:@"two"并找到:Apple Two(白色)

我可以搜索:@"banana一个“并找到:Banana One(黄色)

我也可以搜索:@"Orange"并找到:Pineapple Three(Orange)

但前提是搜索顺序正确

我无法搜索:@"One Banana"@"Yellow One"@"Yellow Banana" 我真的希望能够像这样搜索,也许使用关键字?

也许是这样的?:

for(NSDictionary *wine in mainArray)
{
NSArray *myArray = [searchText componentsSeparatedByString:@" "];
    NSString *wineName = [wine objectForKey:@"name"];
    NSRange range = [wineName rangeOfString:myArray options:NSCaseInsensitiveSearch];
    if(range.location != NSNotFound)
        [searchArray addObject:wine];
}

我知道这真的不行,但我想你知道我的意思吗? 那么,如何搜索例如:@"one banana"并找到:Banana One(黄色)

3 个答案:

答案 0 :(得分:1)

我使用NSPredicate制定了以下解决方案。

    NSArray *objects = @[@"Banana One",@"Apple Two"];
    NSString *searchString = @"one banana";
    NSArray *searchComoponents = [searchString componentsSeparatedByString:@" "];

    NSMutableString *format = [NSMutableString stringWithFormat:@"SELF CONTAINS[c] \"%@\"",[NSString stringWithFormat:@"%@",searchComoponents[0]]];
    for (int i = 1; i < searchComoponents.count; i++) {
        [format appendFormat:@" AND SELF CONTAINS[c] \"%@\"",[NSString stringWithFormat:@"%@",searchComoponents[i]]];
    }
    NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"%@",format]];
    NSArray *filtered = [objects filteredArrayUsingPredicate:predicate];

简短说明:SELF是数组中的当前对象,应该进行校对,CONTAINS查看左对象是否包含正确的对象,[c]使其成为对象所有案例不敏感。 因此,对于searchString中的每个关键字,您都要将条件添加到谓词格式中,以便最后您应该使用以下格式的NSPredicate: SELF CONTAINS [c] object1 AND SELF CONTAINS [c] object2 .... 最后一行使用此NSPredicate创建过滤后的数组。有关谓词格式外观here的更多信息。

答案 1 :(得分:1)

<强>解决

感谢DevFan的回答! 我需要编辑一些东西,例如SELF到SELF.name,以指定我的字典数组中的键。

NSArray *searchComoponentsWithEmptyStrings = [searchText componentsSeparatedByString:@" "];
        NSMutableArray *searchComoponents = [searchComoponentsWithEmptyStrings mutableCopy];
        [searchComoponents removeObject:@""]; //remove empty strings from the array (only works with NSMutableArray)

        NSMutableString *format = [NSMutableString stringWithFormat:@"SELF.name CONTAINS[c] '%@'",[NSString stringWithFormat:@"%@",searchComoponents[0]]];
        for (int i = 1; i < searchComoponents.count; i++) {
            [format appendFormat:@"AND SELF.name CONTAINS[c] '%@'",[NSString stringWithFormat:@"%@",searchComoponents[i]]];
        }
        NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"%@",format]];
        searchArray = [mainArray filteredArrayUsingPredicate:predicate];

现在我也可以搜索@“banana”(最后有空格)并且仍然可以找到Banana One(黄色)

答案 2 :(得分:0)

也许你应该将NSString“Banana One(Yellow)”分成一个数组(“Banana”,“One”,“(Yellow)”)并检查其中一个是否包含在你的搜索文本中。

    NSString *searchText = @"One";
    NSString *txt = @"Banana One (Yellow)";
    NSArray* splitString = [txt componentsSeparatedByString:@" "];
    for(int i = 0; i < [splitString count]; i++){
        if([[splitString objectAtIndex:i] rangeOfString:searchText].location != NSNotFound) {
            return txt;
        }
    }