问题描述
当需要过滤NSArray以获取返回的数组中的项的子集时,哪种方法更频繁且边缘情况更快?
When needing to filter an NSArray to get a subset of the items in the array returned, which method is quicker more frequently and in edge cases?
推荐答案
以下测试(在发布模式下编译,在Mac Pro上执行)表示
filteredArrayUsingPredicate
是如果使用
atextual谓词,则慢于 indexesOfObjectsPassingTest
,但如果使用基于块的谓词则速度更快。
我测试中的禁食方法是一个简单的(快速枚举)循环,它将所有匹配的
对象添加到一个可变数组中。
The following tests (compiled in Release mode, executed on a Mac Pro) indicate thatfilteredArrayUsingPredicate
is slower than indexesOfObjectsPassingTest
if you usea "textual" predicate, but faster if you use block-based predicate.The fasted method in my test was a simple (fast-enumeration) loop that adds all matchingobjects to a mutable array.
结果过滤10,000,000个字典的数组,其中约50%与谓词匹配:
Results for filtering an array of 10,000,000 dictionaries, where about 50% match the predicate:
8.514334 (predicateWithFormat)
4.422550 (predicateWithBlock)
5.170086 (indexesOfObjectsPassingTest)
3.154015 (fast-enumeration + mutable array)
当然结果可能不同其他谓词。
Of course the results may be different for other predicates.
#import <Foundation/Foundation.h>
NSUInteger filter1(NSArray *a)
{
NSPredicate *pred = [NSPredicate predicateWithFormat:@"num > 1000 AND foo == 'bar'"];
NSArray *filtered = [a filteredArrayUsingPredicate:pred];
return [filtered count];
}
NSUInteger filter2(NSArray *a)
{
NSPredicate *pred = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *obj, NSDictionary *bindings) {
return ([obj[@"num"] intValue] > 1000 && [obj[@"foo"] isEqualToString:@"bar"]);
}];
NSArray *filtered = [a filteredArrayUsingPredicate:pred];
return [filtered count];
}
NSUInteger filter3(NSArray *a)
{
NSIndexSet *matching = [a indexesOfObjectsPassingTest:^BOOL(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
return ([obj[@"num"] intValue] > 1000 && [obj[@"foo"] isEqualToString:@"bar"]);
}];
NSArray *filtered = [a objectsAtIndexes:matching];
return [filtered count];
}
NSUInteger filter4(NSArray *a)
{
NSMutableArray *filtered = [NSMutableArray array];
for (NSDictionary *obj in a) {
if ([obj[@"num"] intValue] > 1000 && [obj[@"foo"] isEqualToString:@"bar"]) {
[filtered addObject:obj];
}
}
return [filtered count];
}
void testmethod(NSArray *a, NSUInteger(*method)(NSArray *a))
{
@autoreleasepool {
NSDate *t1 = [NSDate date];
NSUInteger count = method(a);
NSDate *t2 = [NSDate date];
NSLog(@"%f", [t2 timeIntervalSinceDate:t1]);
}
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSMutableArray *a = [NSMutableArray array];
for (int i = 0; i < 10000000; i++) {
[a addObject:@{@"num": @(arc4random_uniform(2000)), @"foo":@"bar"}];
}
testmethod(a, filter1);
testmethod(a, filter2);
testmethod(a, filter3);
testmethod(a, filter4);
}
return 0;
}
这篇关于哪个具有更快的性能indexOfObjectsPassingTest或filteredArrayUsingPredicate?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!