目标c - 按字搜索

时间:2014-08-03 09:32:25

标签: ios objective-c search nspredicate

我有一个书籍应用程序,用户可以浏览和搜索书籍 例如,这是书籍清单:

“腐尸舒适”
“掩盖她的脸”
“没有老人的国家”
“猴子的雨衣”

我想实现一个行为如下的搜索机制:
如果用户搜索“ co <​​/ strong>”,结果将为:

“Carrion Co mfort”
Co ver Her Face”
“没有 Co 为老人统一”

你可以注意到我只想找到以“co”开头的单词,这就是为什么书中的“The Monkey's Raincoat”不在结果中,尽管它包含“co”

为实现这一目标,我创建了一个名为Token的托管对象:

Token  
------
normalizedString  

我添加了与我的Book对象的多对多关系

Book
-----
title  
releaseDate

tokens (to-many)  

现在这就是我的搜索谓词的样子:

[NSPredicate predicateWithFormat:@"SUBQUERY(tokens, $token, $token.normalizedString BEGINSWITH[cd] %@).@count > 0", [searchString lowercaseString]];  

如果我搜索单个单词,这样可以正常工作,例如,如果我搜索“她”,我会得到结果:
“掩盖她的脸”

但是当我尝试搜索多个单词时,例如“她的脸”,我得不到任何结果。

我理解为什么会这样,但在这里找不到合适的解决方案 任何帮助将不胜感激

3 个答案:

答案 0 :(得分:0)

我猜这是一个hackish解决方案,但我会尝试以不同的方式生成令牌。 它不是一个只是一个单词的标记,而是从单词开始并包含以下文本。

为“掩盖她的脸”

而不是

Cover
Her
Face

我会尝试获取令牌:

Cover Her Face
Her Face
Face

然后BEGINSWITH解决方案应该按照您的意图工作。这对你有意义吗?

答案 1 :(得分:0)

假设您将图书存储在NSArray / NSMutableArray NSString*的... {抱歉,我不知道NSPredicate是什么。但是如果你&# 39;能够将您的图书转换为NSString* s然后您可以使用此方法)

NSMutableArray* books = [NSMutableArray arrayWithObjects:   @"Carrion Comfort",
                                                            @"Cover Her Face",
                                                            @"No Country for Old Men",
                                                            @"The Monkey's Raincoat",
                                                            nil ];

[books enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSArray* _tmp = [(NSString*)obj componentsSeparatedByString:@" "];
    [_tmp enumerateObjectsUsingBlock:^(id _obj, NSUInteger idx, BOOL *stop) {
        if ([[_obj substringToIndex:2] isEqualTo:@"co"] ||
            [[_obj substringToIndex:2] isEqualTo:@"Co"])
            NSLog(@"%@", obj);
    }];
}];

它可能不是最有效的方式,但绝对有效。

除了提供所有可能的变化之外,必须有办法处理区分大小写,但我没有时间去弄清楚。也许在比较之前将所有内容转换为小写?

答案 2 :(得分:0)

为了回答我自己的问题,我最终将搜索字符串标记出来并创建了一个更复杂的谓词来处理这些令牌:

- (NSPredicate *)predicateForSearchString:(NSString *)searchString {    
    NSSet *searchTokens = [[Tokenizer sharedTokenizer] tokenize:searchString];

    NSMutableArray *subPreds = [NSMutableArray arrayWithCapacity:searchTokens.count];
    for (NSString *token in searchTokens) {
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"SUBQUERY(tokens, $token, $token.normalizedString BEGINSWITH[cd] %@).@count > 0", token];
        [subPreds addObject:pred];
    }
    return [NSCompoundPredicate andPredicateWithSubpredicates:[subPreds copy]];
}