使用NSPredicate来过滤对象

时间:2015-11-11 20:26:37

标签: ios objective-c filter nspredicate

这里说我有一组具有两个属性的对象:

// array of object
NSArray *objects
// object
NSString *primaryTag;
NSArray *secondaryTag;

因为我想要的是当这个对象包含givenTag时,它可以被传递给一个名为results的新数组;

这是我的代码:

NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"primaryTag == %@ || secondaryTag CONTAINS[c] %@", givenTag, givenTag];
results = [objects filteredArrayUsingPredicate:resultPredicate];

似乎primaryTag运行良好,但secondaryTag无法正常工作,有人可以帮助我。我对NSPredicate过滤并不熟悉。提前谢谢。

4 个答案:

答案 0 :(得分:1)

最有效的方法是NSCompoundPredicate如此:

NSArray *subPredicates = @[tag1, tag2, tag3];
NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];

你的问题有点不清楚所以你可能也想要:

andPredicateWithSubpredicates

具体取决于您要查找的结果集的性质。

请在此处查看Apple文档:NSCompoundPredicate Docs

答案 1 :(得分:1)

我实现了以下自定义类:

name

并覆盖它的NSLog语句的描述方法,以打印我们理解的内容:

@interface CustomObject : NSObject

@property (copy, nonatomic) NSString *primaryTag;
@property (strong, nonatomic) NSArray *secondaryTag;

@end

然后我从自定义类创建了一些对象并将它们添加到数组中:

- (NSString *)description {
  return [NSString stringWithFormat:@"primaryTag: %@, secondaryTag: %@", _primaryTag, [_secondaryTag componentsJoinedByString:@", "]];
}

最后我创建了一个要搜索的字符串和谓词:

NSMutableArray *objects = [NSMutableArray array];

CustomObject *obj1 = [CustomObject new];
obj1.primaryTag = @"stringToSearchFor";
obj1.secondaryTag = @[@"notTheStringToSearchFor", @"somethingElse"];
[objects addObject:obj1];

CustomObject *obj2 = [CustomObject new];
obj2.primaryTag = @"differentString";
obj2.secondaryTag = @[@"nothingWeAreLookingFor"];
[objects addObject:obj2];

CustomObject *obj3 = [CustomObject new];
obj3.primaryTag = @"anotherOne";
obj3.secondaryTag = @[@"whoCaresForThisString", @"stringToSearchFor"];
[objects addObject:obj3];

当我退出结果时,我得到了正确的结果:

NSString *givenTag = @"stringToSearchFor";

NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"primaryTag == %@ || secondaryTag CONTAINS[c] %@", givenTag, givenTag];

日志:

(适用     “primaryTag:stringToSearchFor,secondaryTag:notTheStringToSearchFor,somethingElse”,     “primaryTag:anotherOne,secondaryTag:whoCaresForThisString,stringToSearchFor” )

是obj1和obj3。正确!如果它不适合你,你的代码就会出现其他问题......

答案 2 :(得分:0)

我看到了这个问题,

我的正常做法是两次使用NSPredicate,

这样我就可以在每个步骤跟踪结果: 选项1:

  

NSPredicate * resultPredicate1 = [NSPredicate predicateWithFormat:@“primaryTag ==%@”,givenTag];   results1 = [objects filteredArrayUsingPredicate:resultPredicate1];

     

NSPredicate * resultPredicate2 = [NSPredicate predicateWithFormat:@“secondaryTag CONTAINS [c]%@”,givenTag];   finalResults = [results1 filteredArrayUsingPredicate:resultPredicate2];

选项2: 使用NSCompoundPredicate复合多个过滤。您可以在google和stackOverFlow上轻松找到很多示例。

希望这会有所帮助, 谢谢

答案 3 :(得分:0)

如果我对原始问题的理解不正确,请告诉我,我会调整我的答案。

问题:您有一组具有2个属性的对象。一个是primaryTag,这是一个字符串。第二个是secondaryTags数组,它是一个字符串集合。您希望过滤primaryTag匹配的所有对象,或者搜索字符串与secondaryTag之一匹配的对象。

回答匹配字符串的正确方法是MATCHESCONTAINS

NSPredicate *pPredicate =
    [NSPredicate predicateWithFormat:@"%K CONTAINS[cd] %@",
                                     @"primaryTag", searchString];
NSPredicate *sPredicate =
    [NSPredicate
     predicateWithFormat:@"SUBQUERY(%K, $st, $st CONTAINS[cd] %@).@count > 0",
                         @"secondaryTags", searchString];
NSCompoundPredicate *searchPredicate = 
    [NSCompoundPredicate orPredicateWithSubPredicates:@[ pPredicate, sPredicate ]];

工作原理:第一个谓词是一个简单的匹配。您可以将CONTAINS替换为MATCHES,如果这更符合您希望的那种比较。 [cd]后缀表示不区分大小写且对变音符号不敏感。在搜索/过滤时包含这些内容是正常的,但同样,它取决于您。我使用%K和替换参数,而不是在谓词格式字符串中嵌入属性名称。在生产代码中,该替换参数将是常量。

第二个谓词有点棘手。它使用SUBQUERY()来过滤secondaryTags数组,并且如果至少一个辅助标记与搜索字符串匹配,则将对象返回为匹配。 SUBQUERY()是一个包含3个参数的函数。第一个是被搜索的集合。第二个是临时变量,依次表示集合中的每个项目;它用在第3个参数中。第3个参数是常规谓词。集合中与筛选器匹配的每个项目都包含在SUBQUERY()的输出中。最后,对匹配的辅助标记进行计数(通过@count),如果计数大于零,则认为原始对象已匹配,因此将包含在已过滤的输出中。

最后,我们将这两个谓词组合成一个searchPredicate,现在可用于过滤对象数组。