什么是比较的所有值的有效和伟大的方式NSArray
包含NSNumbers
从floats
找到最大的一个和最小的一个?
任何想法如何做到这一点很好的和快速的在Objective-C?
什么是比较的所有值的有效和伟大的方式NSArray
包含NSNumbers
从floats
找到最大的一个和最小的一个?
任何想法如何做到这一点很好的和快速的在Objective-C?
如果执行速度 (不是编程速度 )是非常重要的,那么一个明确的循环是最快的。 我做了百万个随机数的数组以下测试:
版本1:排序的数组:
NSArray *sorted1 = [numbers sortedArrayUsingSelector:@selector(compare:)];
// 1.585 seconds
版本2:键 - 值编码,使用“中的doubleValue”:
NSNumber *max=[numbers valueForKeyPath:@"@max.doubleValue"];
NSNumber *min=[numbers valueForKeyPath:@"@min.doubleValue"];
// 0.778 seconds
版本3:键 - 值编码,使用“自我”:
NSNumber *max=[numbers valueForKeyPath:@"@max.self"];
NSNumber *min=[numbers valueForKeyPath:@"@min.self"];
// 0.390 seconds
第4版:显式循环:
float xmax = -MAXFLOAT;
float xmin = MAXFLOAT;
for (NSNumber *num in numbers) {
float x = num.floatValue;
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}
// 0.019 seconds
第5版:块列举:
__block float xmax = -MAXFLOAT;
__block float xmin = MAXFLOAT;
[numbers enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
float x = num.floatValue;
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}];
// 0.024 seconds
测试程序创建百万随机数的数组,然后应用于所有分选技术来在相同的阵列。 上面的定时是一个运行的输出,但我做约20在每次运行的结果非常相似运行。 我也改变,其中5种选方法被应用,以排除缓存影响的顺序。
更新:我现在已经创建了一个(希望)更好的测试程序。 完整的源代码是在这里: https://gist.github.com/anonymous/5356982 。 的平均时间进行排序百万随机数的阵列(以秒上的3.1 GHz的酷睿的iMac,释放编译):
Sorting 1.404 KVO1 1.087 KVO2 0.367 Fast enum 0.017 Block enum 0.021
更新2:人们可以看到,快速列举比块列举快(这也是在这里说: http://blog.bignerdranch.com/2337-incremental-arrayification/ )。
编辑:下面是完全错误的 ,因为我忘了初始化用作锁定对象,如热舔正确注意到,所以没有同步在全部完成。 并与lock = [[NSObject alloc] init];
并发枚举是如此缓慢 ,我不敢来显示结果。 也许更快的同步机制,可以帮助...)
如果您添加这极大地改变了 NSEnumerationConcurrent
选项块列举:
__block float xmax = -MAXFLOAT;
__block float xmin = MAXFLOAT;
id lock;
[numbers enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
float x = num.floatValue;
@synchronized(lock) {
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}
}];
这里的时间是
Concurrent enum 0.009
所以它的快两倍,快速列举。 其结果可能是不具有代表性,因为它依赖于可用线程数。 但有趣的反正! 请注意,我已经使用了“最容易使用的”同步方法,这可能不是最快的。
通过NSNumber的包裹下保存,然后浮
NSNumber *max=[numberArray valueForKeyPath:@"@max.doubleValue"];
NSNumber *min=[numberArray valueForKeyPath:@"@min.doubleValue"];
* 不编译和检查,已经与的intValue,不知道双重或浮动检查
解决。 采取的第一个和最后一个元素。
BTW:你在一个NSArray不能店花车,您将需要包起来的NSNumber对象。
NSArray *numbers = @[@2.1, @8.1, @5.0, @.3];
numbers = [numbers sortedArrayUsingSelector:@selector(compare:)];
float min = [numbers[0] floatValue];
float max = [[numbers lastObject] floatValue];
我同意排数组,然后选择第一个和最后一个元素,但我觉得这个解决方案更优雅(这也将非数值对象通过改变块内部的比较工作):
NSArray *unsortedArray = @[@(3), @(5), @(1)];
NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSNumber *item1 = (NSNumber *)obj1;
NSNumber *item2 = (NSNumber *)obj2;
return [item1 compare:item2];
}];
如果你真的想要漂亮,有一个很长的名单,你不想阻止你的主线程,这应该工作:
NSComparator comparison = ^NSComparisonResult(id obj1, id obj2) {
NSNumber *item1 = (NSNumber *)obj1;
NSNumber *item2 = (NSNumber *)obj2;
return [item1 compare:item2];
};
void(^asychSort)(void) = ^
{
NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator:comparison];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"Finished Sorting");
//do your callback here
});
};
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), asychSort);
化繁为简
NSArray *numbers = @[@2.1, @8.1, @5.0, @.3];
numbers = [numbers sortedArrayUsingSelector:@selector(compare:)];
float min = [numbers[0] floatValue];
float max = [[numbers lastObject] floatValue];
NSLog(@"MIN%f",min);
NSLog(@"MAX%f",max);