NSArray 上的 NSPredicate 用于搜索任何对象

Posted

技术标签:

【中文标题】NSArray 上的 NSPredicate 用于搜索任何对象【英文标题】:NSPredicate on an NSArray to search for any object 【发布时间】:2013-09-16 07:45:32 【问题描述】:

我有一个包含名称、地址、电话的对象数组。没有,等等。

我希望能够在数组中搜索任何出现的术语 - 无论是在名称字段、地址字段等中。

我有这样的想法:

-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope 
    // Update the filtered array based on the search text and scope.
    // Remove all objects from the filtered search array


    [self.searchResults removeAllObjects];
    // Filter the array using NSPredicate
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",searchText];
    searchResults = [NSMutableArray arrayWithArray:[contactArray filteredArrayUsingPredicate:predicate]];

这会导致异常“Can't use in/contains operator with collection”。

更新。我现在最多可以搜索三个字段。当我添加第四个(以任何顺序)时,我得到了这个异常:“无法解析格式字符串......”

谓词代码现在是:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.narrative contains[c] %@ OR SELF.category contains[c] %@ OR SELF.date contains[c] OR SELF.name contains[c] %@", searchText, searchText, searchText, searchText];

     searchResults = [NSMutableArray arrayWithArray:[allDreams filteredArrayUsingPredicate:predicate]];

三个是谓词搜索字段的限制吗?我该如何解决这个问题?再次感谢。

【问题讨论】:

【参考方案1】:

只需使用一个谓词字符串来检查它们:

@"name contains[cd] %@ OR address contains[cd] %@"

您可以根据需要添加任意数量。

唯一的缺点是您需要为每个要测试的字段添加相同的搜索字符串,这看起来有点难看。

如果您的对象是字典,那么有一种方法可以真正搜索所有值,而不必在编译时知道它们的名称,使用子查询。

它是这样工作的:

@"subquery(self.@allValues, $av, $av contains %@).@count > 0"

它对字典对象使用@allValues 特殊键(或方法调用,如果您愿意),并使用它来过滤包含您的搜索字符串的任何值。如果找到任何对象(即计数为正),则该对象将包含在结果中。

请注意,这将不加选择地检查所有值,即使是那些您不想包含在字典中的值。

【讨论】:

@DavidDelMonte 注意到它们是两个非常不同的答案——Kjuly 提出了两种检查一个字段的方法,而我的提出了一种检查多个字段的方法。因此,不要只是尝试它们,而是要确保您了解您需要什么以及正确的解决方案是什么。 此外,您可以使用NSCompoundPredicate 动态创建简单的谓词并使用+orPredicateWithSubpredicates: 连接它们。 @all,Monolo 的答案接近我想要的,但我意识到这比我在我的问题中提出的要复杂。我必须弄清楚如何包含特殊字符(例如空格)和来自多个数组的项目 - 包括多对多关系。我认为这将是一个轻松的早晨...... @DavidDelMonte 我的猜测是异常的描述告诉你。但无论如何,您的字符串中存在语法错误:SELF.date 字段缺少%@。所以问题不在于添加的字段数量。 @Ryan 只需将 [CD] 修饰符应用于谓词字符串:“... contains[cd] ...”【参考方案2】:

我认为你的数组项不是纯字符串,对吧?

假设你的数组项包含name属性(即使是字典),你可以这样搜索:

NSPredicate * predicate =
  [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@ OR name LIKE[cd] %@", searchText, searchText];

这里,name 可以是SELF.name


HERE是官方文档。

【讨论】:

Kjuly,在这个数组中,每个对象都是一个字符串对象。我尝试过使用 SELF.name CONTAINS[c],但这只是查看第一个字段。我将尝试使用 [cd]。也感谢您的链接。 @DavidDelMonte 字符串对象怎么会包含名称、地址?你的意思是这样的:name:<name>,address:<address>?为什么不把它格式化成@name: <name>, address: <address>? ;)

以上是关于NSArray 上的 NSPredicate 用于搜索任何对象的主要内容,如果未能解决你的问题,请参考以下文章

NSPredicate 用于过滤数组

NSPredicate 用于多个对象和属性

过滤巨大的 NSArray

NSPredicate 和 NSArray

使用 NSPredicate 搜索 NSArray

NSArray 的 NSArray 中对象属性的 NSPredicate