在NSNumbers的NSArray中find最小和最大的值

什么是一个有效的,伟大的方式来比较NSArray所有值包含floats NSNumbersfind最大的和最小的?

任何想法如何做到这一点很好,在objective-c快速?

如果执行速度 (不是编程速度 )很重要,那么显式循环是最快的。 我用1000000个随机数组做了以下testing:

版本1:对数组进行sorting:

 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 

testing程序将创build一个包含1000000个随机数的数组,然后将所有sorting技术应用于相同的数组。 上面的时间是一次运行的输出,但在每次运行中,我做了大约20次运行,结果非常相似。 我也改变了5种sorting方法的排列顺序来排除caching效果。

更新:我现在已经创build了一个(希望)更好的testing程序。 完整的源代码在这里: https : //gist.github.com/anonymous/5356982 。 对1000000个随机数组进行sorting的平均时间是(以秒为单位,在3.1 GHz Core i5 iMac上,发布编译):

sorting1.404
 KVO1 1.087
 KVO2 0.367
快速枚举0.017
阻止枚举0.021

更新2:正如人们所看到的,快速枚举比块枚举更快(这也在这里陈述: http : //blog.bignerdranch.com/2337-incremental-arrayification/ )。

编辑:以下是完全错误的 ,因为我忘记初始化用作锁的对象,因为热舔正确注意到,所以根本没有同步完成。 并用lock = [[NSObject alloc] init]; 并发枚举太慢 ,我不敢显示结果。 也许更快的同步机制可能会有所帮助…)

如果将NSEnumerationConcurrent选项添加到块枚举中, 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; } }]; 

这里的时间是

并发枚举0.009

所以它是快速查点的两倍。 结果可能不具有代表性,因为它取决于可用的线程数。 不过有意思! 请注意,我使用了“最易于使用”的同步方法,这可能不是最快的。

然后通过包装在NSNumber下保存浮动

 NSNumber *max=[numberArray valueForKeyPath:@"@max.doubleValue"]; NSNumber *min=[numberArray valueForKeyPath:@"@min.doubleValue"]; 

* 没有编译和检查,已经用intValue检查,不确定有关double或float

分类。 采取第一个和最后一个元素。

顺便说一句:你不能存储浮动在一个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]; 

我同意sorting数组,然后select第一个和最后一个元素,但我觉得这个解决scheme更优雅(这也适用于通过改变块内比较非数字对象):

 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); 

任何一个正在寻找Swift 3.x的人 –

 let arrayOfNumbers = [1.0,4.2,10.3,15.2] print(arrayOfNumbers.max() ?? 0.0)//Max number print(arrayOfNumbers.min() ?? 0.0)//Min number