2015-11-11 41 views
0

在这里说,我有对象的两个属性的数组:使用NSPredicate来筛选对象

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

因为我想要的是,当这个对象包含givenTag,它可以被传递到一个新的数组称为结果;

这里是我的代码:

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

看来,primaryTag效果很好,但secondaryTag不起作用,有人可以帮助我。我不熟悉NSPredicate过滤。提前致谢。

回答

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] %@)[email protected] > 0", 
         @"secondaryTags", searchString]; 
NSCompoundPredicate *searchPredicate = 
    [NSCompoundPredicate orPredicateWithSubPredicates:@[ pPredicate, sPredicate ]]; 

工作原理:第一个谓词是一个简单的比赛。你可以用MATCHES代替CONTAINS,如果那样更适合你想要做的比较。后缀[cd]表示不区分大小写且不区分大小写。在搜索/过滤时包含这些属于正常情况,但是,这取决于您。我不使用谓词格式字符串嵌入属性名称,而是使用%K和替换参数。在生产代码中,该替换参数将是一个常量。

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

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

1

最有效的方式做到这一点是一个NSCompoundPredicate像这样:

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

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

andPredicateWithSubpredicates 

根据性质到底是什么你正在寻找的结果集。

看到苹果文档的位置:NSCompoundPredicate Docs

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上轻松找到很多示例。

希望这将帮助, 感谢

1

我实现以下自定义类:

@interface CustomObject : NSObject 

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

@end 

,并推翻它的描述方法为NSLog的语句来打印,我们明白了什么:

- (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]; 

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

NSLog(@"%@", [objects filteredArrayUsingPredicate:resultPredicate]); 

日志:

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

其是OBJ1和OBJ3。正确!如果它不适合你,那么你的代码有其他问题...