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')
– 这将在SELF
(NSDictionary
)上执行-allKeys
并返回NSDictionary
中所有键的NSArray
-
SUBQUERY(allKeys, $k, SELF[$k] contains[cd] %@)
– 这将迭代allKeys
每个项目,每个连续的项目被放置到$k
variables中。 对于每个项目,它将执行SELF[$k] contains %@
。 这基本上会结束:[theDictionary objectForKey:$k] contains[cd] %@
。 如果这返回YES
,那么$k
项目将被聚合成一个新的数组。 -
SUBQUERY(...).@count > 0
– 在find与包含您的search文本的值对应的所有键后,我们检查并查看是否有任何键。 如果有(即数组的大小大于0),那么整个字典将是最终的过滤数组的一部分。
如果可能,我build议采用第一种方法。 SUBQUERY
和FUNCTION
有点神秘,第一个更容易理解。
而另一种方式,你实际上几乎在你的问题上。 而不是做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 } }