将NSArray过滤到Objective-C中的新NSArray中

我有一个NSArray ,我想创build一个新的NSArray与原始数组符合特定条件的对象。 标准由返回BOOL的函数决定。

我可以创build一个NSMutableArray ,遍历源数组,并复制filter函数接受的对象,然后创build一个不可变的版本。

有没有更好的办法?

NSArrayNSMutableArray提供了过滤数组内容的方法。 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 filterUsingPredicate: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. }]]; 

我认为这是简单的。


迅速:

对于那些在Swift中使用NSArray的人,你可能更喜欢这个简洁的版本:

 nsArray = nsArray.filter { $0.shouldIKeepYou() } 

filter只是一个Array的方法( NSArray隐式桥接到Swift的Array )。 它有一个参数:一个闭包,它接受数组中的一个对象并返回一个Bool 。 在你的闭包中,只需要在过滤数组中的任何对象都返回true

如果你是OS X 10.6 / iOS 4.0或更高版本,你可能比NSPredicate更好。 请参阅-[NSArray indexesOfObjectsPassingTest:]或编写自己的类别以添加方便的 – -select:-filter:方法( 示例 )。

要其他人写这个类别,testing等等? 检查BlocksKit ( arrays文档 )。 还有更多的例子可以通过search例如“nsarray block category select”来find 。

基于Clay Bridges的回答,下面是一个使用块进行过滤的例子(将yourArray更改为数组variables名称,将testFunc更改为testing函数的名称):

 yourArray = [yourArray objectsAtIndexes:[yourArray indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { return [self testFunc:obj]; }]]; 

假设你的对象都是一个类似的types,你可以添加一个方法作为他们的基类的一个类别,调用你的标准使用的函数。 然后创build一个引用该方法的NSPredicate对象。

在某些类别中定义使用你的函数的方法

 @implementation BaseClass (SomeCategory) - (BOOL)myMethod { return someComparisonFunction(self, whatever); } @end 

那么无论你在哪里过滤:

 - (NSArray *)myFilteredObjects { NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMethod = TRUE"]; return [myArray filteredArrayUsingPredicate:pred]; } 

当然,如果你的函数只能和你的类中的属性进行比较,那么把函数的条件转换成谓词string可能会更容易一些。

NSPredicateNSPredicate构造条件以过滤集合( NSArrayNSSetNSDictionary )的方式。

例如,考虑两个数组arrfilteredarr

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"]; filteredarr = [NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]]; 

filteredarr肯定会包含单独包含字符c的项目。

让它很容易记住那些小小的sql背景

 *--select * from tbl where column1 like '%a%'--* 

1)select * from tbl – > collection

2)column1 like'%a%' – > NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];

3)select * from tbl where column1 like'%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; }];