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

时间:2020-03-06 14:30:03  来源:igfitidea点击:

我有一个" NSArray",我想用满足特定条件的原始数组中的对象创建一个新的" NSArray"。该标准由返回BOOL的函数决定。

我可以创建一个" NSMutableArray",遍历源数组,然后复制过滤器函数接受的对象,然后创建它的不可变版本。

有没有更好的办法?

解决方案

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对象。

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

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

然后,无论我们在哪里过滤:

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

当然,如果函数仅与类中可访问的属性进行比较,则将函数的条件转换为谓词字符串可能会更容易。

如果我们使用的是OS X 10.6 / iOS 4.0或者更高版本,则使用块可能要比使用NSPredicate更好。参见-[NSArray indexsOfObjectsPassingTest:]或者编写自己的类别以添加方便的-select:或者-filter:方法(示例)。

希望其他人编写该类别,对其进行测试等吗?请查看BlocksKit(数组文档)。通过搜索例如可以找到更多示例。 " nsarray块类别选择"。