在 Objective-C 中将 NSArray 过滤为新的 NSArray
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/110332/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
filtering NSArray into a new NSArray in Objective-C
提问by lajos
I have an NSArrayand I'd like to create a new NSArraywith objects from the original array that meet certain criteria. The criteria is decided by a function that returns a BOOL.
我有一个NSArray,我想NSArray用原始数组中满足特定条件的对象创建一个新对象。标准由返回 a 的函数决定BOOL。
I can create an NSMutableArray, iterate through the source array and copy over the objects that the filter function accepts and then create an immutable version of it.
我可以创建一个NSMutableArray,遍历源数组并复制过滤器函数接受的对象,然后创建它的不可变版本。
Is there a better way?
有没有更好的办法?
回答by lajos
NSArrayand NSMutableArrayprovide methods to filter array contents. NSArrayprovides filteredArrayUsingPredicate:which returns a new array containing objects in the receiver that match the specified predicate. NSMutableArrayadds filterUsingPredicate:which evaluates the receiver's content against the specified predicate and leaves only objects that match. These methods are illustrated in the following example.
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" }
回答by Stuart
There are loads of ways to do this, but by far the neatest is surely using [NSPredicate predicateWithBlock:]:
有很多方法可以做到这一点,但到目前为止,最好的肯定是使用[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.
}]];
I think that's about as concise as it gets.
我认为这是尽可能简洁的。
Swift:
迅速:
For those working with NSArrays in Swift, you may prefer this even moreconcise version:
对于那些NSArray在 Swift 中使用s 的人,你可能更喜欢这个更简洁的版本:
nsArray = nsArray.filter { yourArray = [yourArray objectsAtIndexes:[yourArray indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return [self testFunc:obj];
}]];
.shouldIKeepYou() }
filteris just a method on Array(NSArrayis implicitly bridged to Swift's Array). It takes one argument: a closure that takes one object in the array and returns a Bool. In your closure, just return truefor any objects you want in the filtered array.
filter只是Array(NSArray隐式桥接到 Swift 的Array)上的一个方法。它接受一个参数:一个闭包,它接受数组中的一个对象并返回一个Bool. 在您的闭包中,只需true在过滤后的数组中返回您想要的任何对象。
回答by pckill
Based on an answer by Clay Bridges, here is an example of filtering using blocks (change yourArrayto your array variable name and testFuncto the name of your testing function):
根据 Clay Bridges 的回答,以下是使用块进行过滤的示例(更改yourArray为数组变量名称和testFunc测试函数的名称):
@implementation BaseClass (SomeCategory)
- (BOOL)myMethod {
return someComparisonFunction(self, whatever);
}
@end
回答by Clay Bridges
If you are OS X 10.6/iOS 4.0 or later, you're probably better off with blocks than NSPredicate. See -[NSArray indexesOfObjectsPassingTest:]or write your own category to add a handy -select:or -filter:method (example).
如果您使用的是 OS X 10.6/iOS 4.0 或更高版本,则使用块可能比使用 NSPredicate 更好。查看-[NSArray indexesOfObjectsPassingTest:]或编写您自己的类别以添加方便-select:或-filter:方法(示例)。
Want somebody else to write that category, test it, etc.? Check out BlocksKit(array docs). And there are manymore examples to be found by, say, searching for e.g. "nsarray block category select".
想要其他人编写该类别、对其进行测试等吗?查看BlocksKit(数组文档)。而且还有很多更多的例子来,比方说可以发现,搜索如“的NSArray块类别中选择”。
回答by Ashley Clark
Assuming that your objects are all of a similar type you could add a method as a category of their base class that calls the function you're using for your criteria. Then create an NSPredicate object that refers to that method.
假设您的对象都是类似的类型,您可以添加一个方法作为其基类的类别,该类调用您用于标准的函数。然后创建一个引用该方法的 NSPredicate 对象。
In some category define your method that uses your function
在某些类别中定义使用您的功能的方法
- (NSArray *)myFilteredObjects {
NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMethod = TRUE"];
return [myArray filteredArrayUsingPredicate:pred];
}
Then wherever you'll be filtering:
那么无论你在哪里过滤:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];
filteredarr = [NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];
Of course, if your function only compares against properties reachable from within your class it may just be easier to convert the function's conditions to a predicate string.
当然,如果您的函数仅与类中可访问的属性进行比较,则将函数的条件转换为谓词字符串可能会更容易。
回答by Durai Amuthan.H
NSPredicateis nextstep's way of constructing condition to filter a collection (NSArray, NSSet, NSDictionary).
NSPredicate是 nextstep 构建条件以过滤集合 ( NSArray, NSSet, NSDictionary) 的方法。
For example consider two arrays arrand filteredarr:
例如考虑两个数组arr和filteredarr:
*--select * from tbl where column1 like '%a%'--*
the filteredarr will surely have the items that contains the character c alone.
Filterarr 肯定会包含单独包含字符 c 的项目。
to make it easy to remember those who little sql background it is
为了方便记住那些没有sql背景的人
[NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];
1)select * from tbl--> collection
1) 从 tbl 中选择 *--> 集合
2)column1 like '%a%'--> NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];
2)column1 像 '%a%'-->NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];
3)select * from tbl where column1 like '%a%'-->
3)select * from tbl where column1 like '%a%'-->
@interface NSArray (X)
/**
* @return new NSArray with objects, that passing test block
*/
- (NSArray *)filteredArrayPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate;
@end
I hope this helps
我希望这有帮助
回答by skywinder
NSArray+X.h
NSArray+Xh
@implementation NSArray (X)
- (NSArray *)filteredArrayPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
{
return [self objectsAtIndexes:[self indexesOfObjectsPassingTest:predicate]];
}
@end
NSArray+X.m
NSArray+Xm
NSArray* youngHeroes = [self.heroes filter:^BOOL(Hero *object) {
return object.age.intValue < 20;
}];
回答by Jordi Puigdellívol
Checkout this library
签出这个库
https://github.com/BadChoice/Collection
https://github.com/BadChoice/Collection
It comes with lots of easy array functions to never write a loop again
它带有许多简单的数组函数,再也不用写循环了
So you can just do:
所以你可以这样做:
NSArray* oldHeroes = [self.heroes reject:^BOOL(Hero *object) {
return object.age.intValue < 20;
}];
or
或者
- (NSArray *) filter:(NSArray *)array where:(NSString *)key is:(id)value{
NSMutableArray *temArr=[[NSMutableArray alloc] init];
for(NSDictionary *dic in self)
if([dic[key] isEqual:value])
[temArr addObject:dic];
return temArr;
}
回答by jalmatari
The Best and easy Way is to create this method And Pass Array And Value:
最好和简单的方法是创建这个方法并传递数组和值:
##代码##
