如何使用NSPredicate在字符串中查找以某个单词开头的内容?

42

我正在寻找一个关于如何使用 NSPredicate 在文本字符串中搜索正确单词的解决方案。目前,我正在使用以下代码:

NSPredicate *predicate = [NSPredicate predicateWithFormat:
                          @"(content CONTAINS[c] %@)", word];

但如果单词很短,它会返回错误的结果,例如:如果单词是“ail”,它会返回包含这3个字母的所有字符串..但我不需要这样抽象的搜索,那么如何在字符串中搜索以我的单词开头的单词呢?


通常建议也进行不区分音符的搜索。这可以通过使用CONTAINS[cd]来实现;添加d即可。 - meaning-matters
5个回答

71

只需使用BEGINSWITH而不是CONTAINS

编辑

如果您需要在字符串的每个单词中进行搜索,可以使用一种技术,该技术在WWDC 2010的其中一个演讲中介绍过。基本思想是创建一个单独的实体Word,它包含一个单词和包含对象(您要搜索的实体)的引用。然后,在Word实体上进行搜索,并返回与找到的单词相关的对象。

查询可能如下所示(假设您的实体与Word之间存在多对一的关系):"ANY words BEGINSWITH[c]%@"

这意味着您在创建对象时必须设置单词。


谢谢您的时间,但我说的是字符串,而不是单词。如果我使用beginswith,它将返回所有以我的单词开头的字符串,但我需要返回包含单词、以我的单词开头的字符串... - azia
所以你需要的是类似于“内容中任何单词以XX开头”的东西? - Alfonso
是的,类似这样。但它应该返回整个字符串。问题是,我需要通过食谱标题在我的核心数据中查找包含其中一个配料的食谱。例如,如果我搜索苹果,我需要找到标题为“富士苹果塔”的食谱。 - azia
我编辑了我的答案,以便为您提供如何实现的示例。这是来自WWDC 2010核心数据演讲的内容,所以如果您是注册开发者,可以观看这些视频。 - Alfonso
@Azia 我建议在这种情况下使用“包含”。 - Dave DeLong
这对我来说很奇怪,但如果我只使用 "content beginswith[c] %@" - 它也能正确工作。因此,你的第一个答案也是正确的。谢谢! - azia

26

BEGINSWITH关键字搜索"Foo",这将帮助您找到一个字符串的起始位置。

"Foo Word1 Word2", "Foo OtherWord1 OtherWord2" (will find 2)

然后使用CONTAINS并搜索“ Foo”(请注意,Foo前面有一个空格),这将返回以空格开头的单词,其后紧跟"Foo"

"Word1 Foo Word", "Some OtherWord FooWord", "Misc    FooXWord" (will find 3)

谓词:

NSPredicate *predicate = [NSPredicate predicateWithFormat:
                          @"(content BEGINSWITH[c] %@) OR (content CONTAINS[c] %@)", word, [NSString stringWithFormat:@" %@", word]];

1
这就是我想要的...非常聪明的回答...谢谢伙计。 - guru

7
如果您的文本在单词之间包含一些标点符号,您可以使用这个谓词:
NSPredicate *predicate = [NSPredicate predicateWithFormat:
                              @"(name BEGINSWITH[c] %@) OR (name MATCHES[c] %@)", 
                              query,
                              [NSString stringWithFormat:@".*[^\\w]%@.*", query]];

哇!我以为分词是唯一的解决方案,直到我看到这个。 - 8suhas
1
这个做法比被接受的答案更加简单且可能更好。 - Daniel
正则表达式速度较慢,最好搜索以空格为前缀的常规字符串。 - Peter Lapisu
[^\\w] 可以被替换为 \\b。在这里,BEGINSWITH 部分是多余的 + 直接将请求输入注入到搜索模式中并不明智。你至少应该先使用 escapedPatternForString: 转义正则表达式符号。 - The Dreams Wind

7

我曾经遇到过同样的问题,一开始我以为你的答案能帮助我,但是没有。这个答案帮了我,所以……看一下:

NSString *matchString =  [NSString stringWithFormat: @".*\\b%@.*",searchText];
NSString *predicateString = @"keyword MATCHES[c] %@";
NSPredicate *predicate =[NSPredicate predicateWithFormat: predicateString, matchString];

哇,这个工作得非常好。我的一些单词在 ( ) 之间,例如 Hello (world),而您的解决方案与 searchText == "w" 匹配。谢谢。如果您有时间,请解释一下这是如何工作的,我不熟悉 \b - meaning-matters
1
将请求输入直接注入到搜索模式中并不明智。您至少应该先使用escapedPatternForString:转义正则表达式符号。 - The Dreams Wind

0

尝试使用复合语句:

NSCompoundPredicate *bPredicate =  [NSCompoundPredicate orPredicateWithSubpredicates:@[[NSPredicate predicateWithFormat:@"content BEGINSWITH[cd] %@",_SearchBar.text], [NSPredicate predicateWithFormat:@"content CONTAINS[cd] %@", _SearchBar.text]]];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接