使用 NSPredicate 过滤对象
use NSPredicate to filter object
假设我有一个具有两个属性的对象数组:
// array of object
NSArray *objects
// object
NSString *primaryTag;
NSArray *secondaryTag;
因为我想要的是当 this 对象包含 givenTag 时,它可以传递给一个名为 results 的新数组;
这是我的代码:
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"primaryTag == %@ || secondaryTag CONTAINS[c] %@", givenTag, givenTag];
results = [objects filteredArrayUsingPredicate:resultPredicate];
貌似primaryTag很好用,secondaryTag不行,谁能帮帮我。我不太熟悉 NSPredicate 过滤。提前致谢。
最有效的方法是使用 NSCompoundPredicate
,如下所示:
NSArray *subPredicates = @[tag1, tag2, tag3];
NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
你的问题有点不清楚所以你可能还想:
andPredicateWithSubpredicates
具体取决于您要查找的结果集的性质。
在此处查看 Apple 文档:NSCompoundPredicate Docs
我看到了这个问题,
我的正常做法是使用 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 和 Whosebug 上轻松找到许多示例。
希望这会有所帮助,
谢谢
我实现了以下自定义 class:
@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:@", "]];
}
然后我从自定义 class 创建了一些对象并将它们添加到数组中:
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。正确的!如果它对您不起作用,那么您的代码一定有其他问题...
如果我对原问题的理解不正确,请告诉我,我会调整我的答案。
问题:您有一个具有 2 个属性的对象数组。一个是 primaryTag
,这是一个字符串。第二个是secondaryTags
的数组,是字符串的集合。您想要过滤 primaryTag
匹配或搜索字符串与 secondaryTag
之一匹配的所有对象。
答案 匹配字符串的正确方法是通过 MATCHES
或 CONTAINS
.
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]
后缀表示不区分大小写和变音符号。在 searching/filtering 时包含那些是正常的,但同样,这取决于您。我没有在谓词格式字符串中嵌入 属性 名称,而是使用 %K
和一个替换参数。在生产代码中,该替换参数将是一个常量。
第二个谓词有点棘手。它使用 SUBQUERY()
来过滤 secondaryTags
数组,如果至少有一个辅助标记与搜索字符串匹配,则 returns 对象匹配。 SUBQUERY()
是一个有 3 个参数的函数。第一个是正在搜索的集合。第二个是一个临时变量,依次表示集合中的每个项目;它用于第三个参数。第三个参数是一个正则谓词。集合中与过滤器匹配的每个项目都包含在 SUBQUERY()
的输出中。最后,对匹配的二级标签进行计数(通过@count
),如果计数大于零,则认为原始对象已匹配,因此将包含在过滤输出中。
最后,我们将这两个谓词合并为一个 searchPredicate
,现在可以用来过滤您的对象数组。
假设我有一个具有两个属性的对象数组:
// array of object
NSArray *objects
// object
NSString *primaryTag;
NSArray *secondaryTag;
因为我想要的是当 this 对象包含 givenTag 时,它可以传递给一个名为 results 的新数组;
这是我的代码:
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"primaryTag == %@ || secondaryTag CONTAINS[c] %@", givenTag, givenTag];
results = [objects filteredArrayUsingPredicate:resultPredicate];
貌似primaryTag很好用,secondaryTag不行,谁能帮帮我。我不太熟悉 NSPredicate 过滤。提前致谢。
最有效的方法是使用 NSCompoundPredicate
,如下所示:
NSArray *subPredicates = @[tag1, tag2, tag3];
NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
你的问题有点不清楚所以你可能还想:
andPredicateWithSubpredicates
具体取决于您要查找的结果集的性质。
在此处查看 Apple 文档:NSCompoundPredicate Docs
我看到了这个问题,
我的正常做法是使用 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 和 Whosebug 上轻松找到许多示例。
希望这会有所帮助, 谢谢
我实现了以下自定义 class:
@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:@", "]];
}
然后我从自定义 class 创建了一些对象并将它们添加到数组中:
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。正确的!如果它对您不起作用,那么您的代码一定有其他问题...
如果我对原问题的理解不正确,请告诉我,我会调整我的答案。
问题:您有一个具有 2 个属性的对象数组。一个是 primaryTag
,这是一个字符串。第二个是secondaryTags
的数组,是字符串的集合。您想要过滤 primaryTag
匹配或搜索字符串与 secondaryTag
之一匹配的所有对象。
答案 匹配字符串的正确方法是通过 MATCHES
或 CONTAINS
.
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]
后缀表示不区分大小写和变音符号。在 searching/filtering 时包含那些是正常的,但同样,这取决于您。我没有在谓词格式字符串中嵌入 属性 名称,而是使用 %K
和一个替换参数。在生产代码中,该替换参数将是一个常量。
第二个谓词有点棘手。它使用 SUBQUERY()
来过滤 secondaryTags
数组,如果至少有一个辅助标记与搜索字符串匹配,则 returns 对象匹配。 SUBQUERY()
是一个有 3 个参数的函数。第一个是正在搜索的集合。第二个是一个临时变量,依次表示集合中的每个项目;它用于第三个参数。第三个参数是一个正则谓词。集合中与过滤器匹配的每个项目都包含在 SUBQUERY()
的输出中。最后,对匹配的二级标签进行计数(通过@count
),如果计数大于零,则认为原始对象已匹配,因此将包含在过滤输出中。
最后,我们将这两个谓词合并为一个 searchPredicate
,现在可以用来过滤您的对象数组。