【问题标题】:Objective c - search by wordObjective c - 按单词搜索
【发布时间】: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 索引。 (查一下。应该有几种算法被提出。)
  • 在我看来,当你应该使用两块石头时,你却试图用同一块石头击中两只鸟。当您的用户点击空间时,您不再需要检查前缀,而只需要检查包含?

标签: ios objective-c search nspredicate


【解决方案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]];
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-28
        • 1970-01-01
        • 2021-07-11
        相关资源
        最近更新 更多