Answers:
NSArray
并NSMutableArray
提供过滤数组内容的方法。NSArray
提供filteredArrayUsingPredicate:返回一个新数组,该数组包含接收器中与指定谓词匹配的对象。NSMutableArray
添加filterUsingPredicate:根据指定的谓词评估接收者的内容,仅保留匹配的对象。在下面的示例中说明了这些方法。
NSMutableArray *array =
[NSMutableArray arrayWithObjects:@"Bill", @"Ben", @"Chris", @"Melissa", nil];
NSPredicate *bPredicate =
[NSPredicate predicateWithFormat:@"SELF beginswith[c] 'b'"];
NSArray *beginWithB =
[array filteredArrayUsingPredicate:bPredicate];
// beginWithB contains { @"Bill", @"Ben" }.
NSPredicate *sPredicate =
[NSPredicate predicateWithFormat:@"SELF contains[c] 's'"];
[array filteredArrayUsingPredicate:sPredicate];
// array now contains { @"Chris", @"Melissa" }
有很多方法可以做到这一点,但是到目前为止,最肯定的方法是使用[NSPredicate predicateWithBlock:]
:
NSArray *filteredArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [object shouldIKeepYou]; // Return YES for each object you want in filteredArray.
}]];
我认为这简明扼要。
对于那些工作NSArray
S IN斯威夫特,你可能更喜欢这种更简洁的版本:
nsArray = nsArray.filter { $0.shouldIKeepYou() }
filter
只是Array
(NSArray
隐式桥接到Swift的Array
)的方法。它带有一个参数:一个闭包,该闭包在数组中使用一个对象并返回一个Bool
。在关闭时,只需返回true
过滤数组中所需的任何对象即可。
NSPredicate predicateWithBlock:
API 需要@Kaitain绑定。
bindings
词典可以包含模板的变量绑定。
根据Clay Bridges的回答,这是一个使用块进行过滤的示例(更改yourArray
为数组变量名称和testFunc
测试函数的名称):
yourArray = [yourArray objectsAtIndexes:[yourArray indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return [self testFunc:obj];
}]];
filteredArrayUsingPredicate
比较精简,但您不使用任何谓词的事实掩盖了目的。
Implicit conversion of 'NSUInteger' (aka 'unsigned long') to 'NSIndexSet * _Nonnull' is disallowed with ARC
...它期望NSIndexSets
indexOfObjectPassingTest
而不是indexesOfObjectsPassingTest
。容易错过,但与众不同:)
如果您使用的是OS X 10.6 / iOS 4.0或更高版本,则使用块可能要比使用NSPredicate更好。见-[NSArray indexesOfObjectsPassingTest:]
或写自己的类增加一个方便-select:
或-filter:
方法(例如)。
希望其他人编写该类别,对其进行测试等吗?查看BlocksKit(array docs)。而且还有很多更多的例子来,比方说可以发现,搜索如“的NSArray块类别中选择”。
假设您的对象都是相似的类型,则可以添加一个方法作为其基类的类别,该方法调用您用于条件的函数。然后创建一个引用该方法的NSPredicate对象。
在某些类别中定义使用函数的方法
@implementation BaseClass (SomeCategory)
- (BOOL)myMethod {
return someComparisonFunction(self, whatever);
}
@end
然后,无论您在哪里过滤:
- (NSArray *)myFilteredObjects {
NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMethod = TRUE"];
return [myArray filteredArrayUsingPredicate:pred];
}
当然,如果您的函数仅与类中可访问的属性进行比较,则将函数的条件转换为谓词字符串可能会更容易。
NSPredicate
是建设条件进行筛选集合NEXTSTEP的方式(NSArray
,NSSet
,NSDictionary
)。
例如考虑两个数组arr
和filteredarr
:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];
filteredarr = [NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];
filterarr肯定会包含仅包含字符c的项。
使容易记住那些小sql背景的人是
*--select * from tbl where column1 like '%a%'--*
1)从* tbl中选择* ->集合
2)像'%a%'这样的column1- >NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];
3)从tbl中选择*,其中column1喜欢'%a%' ->
[NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];
我希望这有帮助
NSArray + Xh
@interface NSArray (X)
/**
* @return new NSArray with objects, that passing test block
*/
- (NSArray *)filteredArrayPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate;
@end
NSArray + Xm
@implementation NSArray (X)
- (NSArray *)filteredArrayPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
{
return [self objectsAtIndexes:[self indexesOfObjectsPassingTest:predicate]];
}
@end
签出这个图书馆
https://github.com/BadChoice/Collection
它带有许多简单的数组函数,不再需要编写循环
因此,您可以执行以下操作:
NSArray* youngHeroes = [self.heroes filter:^BOOL(Hero *object) {
return object.age.intValue < 20;
}];
要么
NSArray* oldHeroes = [self.heroes reject:^BOOL(Hero *object) {
return object.age.intValue < 20;
}];