NSPredicate匹配“NSDatabase中包含一个string的值的任何条目”

我有一系列字典,类似于以下内容:

 (
         {
            黑色=“?”;
            date=“????。??”
            结果=“*”;
             SourceDate =“2007.10.24”;
            白=“配对模式#1”;
         },
         {
            黑色=“?”;
            date=“????。??”
            结果=“*”;
             SourceDate =“2008.10.24”;
            白=“关于本出版物”;
         }
 )

我想让用户能够在“白色”和“黑色”字段内或任何字段内search文本。 我有一个NSPredicate来做特定的领域:

predicate = [NSPredicate predicateWithFormat:@"self.Black contains[cd] %@ or self.White contains[cd] %@", searchText, searchText]; [filteredGames addObjectsFromArray:[games filteredArrayUsingPredicate:predicate]]; 

我想不出如何为一个谓词返回一个谓词,这个谓词将返回与文本匹配的任何对象的字典。 即我可以search“2007”,它会返回第一个字典,但不是第二个。 我尝试了我自己并不真正期待的“自我。*”,并且还“更自我。所有的价值”,这是我更有希望的。 事实上我并不知道密钥是什么,因此需要一些不太具体的东西。

有什么build议么?

如果所有的字典都有相同的密钥,那么你可以做一些非常简单的事情:

 NSArray *keys = ...; //the list of keys that all of the dictionaries contain NSMutableArray *subpredicates = [NSMutableArray array]; for (NSString *key in keys) { NSPredicate *subpredicate = [NSPredicate predicateWithFormat:@"%K contains[cd] %@", key, searchText]; [subpredicates addObject:subpredicate]; } NSPredicate *filter = [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates]; 

然后你可以使用filter来过滤你的NSArray (使用-filteredArrayUsingPredicate )。

另一方面,如果你有一个任意字典的数组都有不同的密钥,你需要一些更蹩脚的东西:

 NSPredicate *filter = [NSPredicate predicateWithFormat:@"SUBQUERY(FUNCTION(SELF, 'allKeys'), $k, SELF[$k] contains[cd] %@).@count > 0", searchText]; 

关于这是做什么的一点点:

  • FUNCTION(SELF, 'allKeys') – 这将在SELFNSDictionary )上执行-allKeys并返回NSDictionary中所有键的NSArray
  • SUBQUERY(allKeys, $k, SELF[$k] contains[cd] %@) – 这将迭代allKeys每个项目,每个连续的项目被放置到$kvariables中。 对于每个项目,它将执行SELF[$k] contains %@ 。 这基本上会结束: [theDictionary objectForKey:$k] contains[cd] %@ 。 如果这返回YES ,那么$k项目将被聚合成一个新的数组。
  • SUBQUERY(...).@count > 0 – 在find与包含您的search文本的值对应的所有键后,我们检查并查看是否有任何键。 如果有(即数组的大小大于0),那么整个字典将是最终的过滤数组的一部分。

如果可能,我build议采用第一种方法。 SUBQUERYFUNCTION有点神秘,第一个容易理解。


而另一种方式,你实际上几乎在你的问题上。 而不是做ANY SELF.allValues contains[cd] %@ ,你可以做ANY FUNCTION(SELF, 'allValues') contains[cd] %@ 。 这相当于我的SUBQUERY疯狂,但更简单。 对于使用ANY (我通常忘记它存在)的想法的荣誉。

编辑

SELF.allValues不起作用的原因是,这被解释为一个keypath,并且-[NSDictionary valueForKey:] 应该和 -[NSDictionary objectForKey:] 。 这里的问题是,如果你用@前缀,那么它会转发到[super valueForKey:] ,这做你期待的。 所以你可以这样做:

 ANY SELF.@allValues contains[cd] %@ 

或者干脆:

 ANY @allValues contains[cd] %@ 

这将工作(并且是最好和最简单的方法)。

如果你想匹配字典中的对象,你可以通过使用for循环来做到这一点,但这可能是一个耗时的任务 –

 for(int i=0; i< [array count]; i++) { NSDictionary *dic = [array objectAtIndex:i]; if([[dic objectForKey:@"Black"] isEqualToString:@"2007"]) { //here is the match } }