在NSNumbers的NSArray中find最小和最大的值
什么是一个有效的,伟大的方式来比较NSArray
所有值包含floats
NSNumbers
find最大的和最小的?
任何想法如何做到这一点很好,在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