Objective c - 按单词搜索
Posted
技术标签:
【中文标题】Objective c - 按单词搜索【英文标题】:Objective c - search by word 【发布时间】:2014-08-03 09:32:25 【问题描述】:我有一个图书应用,用户可以在其中浏览和搜索图书。 例如这是书籍列表:
“腐肉舒适” “遮住她的脸” “老人无国” 《猴子的雨衣》
我想实现一个行为如下的搜索机制: 如果用户搜索“co”,结果将是:
“Carrion Comfort” “认识她的脸” “老人没有合作”
你可以注意到我只想找到以“co”开头的单词,这就是为什么“猴子的雨衣”这本书虽然包含“co”却不在结果中
为此,我创建了一个名为 Token
的托管对象:
Token
------
normalizedString
我在 Book 对象中添加了一对多关系
Book
-----
title
releaseDate
tokens (to-many)
现在这就是我的搜索谓词的样子:
[NSPredicate predicateWithFormat:@"SUBQUERY(tokens, $token, $token.normalizedString BEGINSWITH[cd] %@).@count > 0", [searchString lowercaseString]];
如果我搜索单个单词,这很好用,例如,如果我搜索“她”,我会得到结果: “捂脸”
但是当我尝试搜索多个单词时,例如“她的脸”,我没有得到任何结果。
我明白为什么会发生这种情况,但在这里找不到正确的解决方案。 任何帮助将不胜感激
【问题讨论】:
您显然想要的是 KWIK 索引。 (查一下。应该有几种算法被提出。) 在我看来,当你应该使用两块石头时,你却试图用同一块石头击中两只鸟。当您的用户点击空间时,您不再需要检查前缀,而只需要检查包含? 【参考方案1】:我猜这是一个骇人听闻的解决方案,但我会尝试以不同的方式生成令牌。 记号不仅仅是一个词,而是从一个词开始并包含以下文本。
为了“遮住她的脸”
代替
Cover
Her
Face
我会尝试获取令牌:
Cover Her Face
Her Face
Face
然后,BEGINSWITH 解决方案应该按您的预期工作。这对你有意义吗?
【讨论】:
【参考方案2】:假设您将书籍存储在 NSString*
s 的 NSArray
/NSMutableArray
...(抱歉,我不知道 NSPredicate
是什么。但是如果您能够将书籍转换为 @ 987654325@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);
];
];
这可能不是最有效的方法,但绝对有效。
除了提供所有可能的变化之外,必须有一种方法来处理区分大小写,但我真的没有时间弄清楚。也许在比较之前将所有内容都转换为小写?
【讨论】:
【参考方案3】:为了回答我自己的问题,我最终对搜索字符串进行了标记,并创建了一个更复杂的谓词来处理这些标记:
- (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]];
【讨论】:
以上是关于Objective c - 按单词搜索的主要内容,如果未能解决你的问题,请参考以下文章