找到NSNumbers的NSArray中最小和最大的值 [英] Finding the smallest and biggest value in NSArray of NSNumbers
问题描述
如何比较包含 NSNumbers
的 NSArray
的所有值的有效方法c> floats 找到最大的和最小的一个?
任何想法如何做这个漂亮和快速在
版本1:对数组排序:
< $ p>
NSArray * sorted1 = [numbers sortedArrayUsingSelector:@selector(compare :)];
// 1.585秒
版本2:使用doubleValue的键值编码:
NSNumber * max = [numbers valueForKeyPath:@@ max.doubleValue];
NSNumber * min = [numbers valueForKeyPath:@@ min.doubleValue];
// 0.778秒
版本3:使用self的键值编码:
NSNumber * max = [numbers valueForKeyPath:@@ max.self];
NSNumber * min = [numbers valueForKeyPath:@@ min.self];
// 0.390秒
版本4:显式循环:
float xmax = -MAXFLOAT;
float xmin = MAXFLOAT;
for(NSNumber * num in numbers){
float x = num.floatValue;
if(x if(x> xmax)xmax = x;
}
// 0.019秒
版本5:阻止枚举:
__ block float xmax = -MAXFLOAT;
__block float xmin = MAXFLOAT;
[numbers enumerateObjectsUsingBlock:^(NSNumber * num,NSUInteger idx,BOOL * stop){
float x = num.floatValue;
if(x if(x> xmax)xmax = x;
}];
// 0.024秒
测试程序创建一个包含1000000个随机数的数组,然后应用所有的排序
技术到同一个数组。上面的时间是一次运行的输出,但是我做了大约20次运行,每次运行都有非常相似的结果。我还更改了应用5种排序方法以排除缓存效果的顺序。
更新:更好的测试程序。完整的源代码位于: https://gist.github.com/anonymous/5356982 。对1000000个随机数的
数组进行排序的平均次数为(以秒为单位,在3.1GHz的Core i5 iMac上,发布编译):
排序1.404
KVO1 1.087
KVO2 0.367
快速枚举0.017
块枚举0.021
$ b b
Update 2:可以看到,快速枚举比块枚举更快(这也在这里说明: http://blog.bignerdranch.com/2337-incremental-arrayification/ )。
编辑:以下是完全错误,因为我忘记初始化用作锁的对象,因为Hot Licks正确地注意到了,所以不进行任何同步。
和 lock = [[NSObject alloc] init];
并发枚举是这样慢
我不敢以显示结果。也许更快的同步机制可能
help ...)
如果添加 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
所以它的速度是快速枚举的两倍。结果可能不是有代表性的
,因为它取决于可用的线程数。但有趣的反正!注意,I
使用了最易于使用的同步方法,这可能不是最快的。
What's an effective and great way to compare all the values of NSArray
that contains NSNumbers
from floats
to find the biggest one and the smallest one?
Any ideas how to do this nice and quick in objective-c
?
If execution speed (not programming speed) is important, then an explicit loop is the fastest. I made the following tests with an array of 1000000 random numbers:
Version 1: sort the array:
NSArray *sorted1 = [numbers sortedArrayUsingSelector:@selector(compare:)];
// 1.585 seconds
Version 2: Key-value coding, using "doubleValue":
NSNumber *max=[numbers valueForKeyPath:@"@max.doubleValue"];
NSNumber *min=[numbers valueForKeyPath:@"@min.doubleValue"];
// 0.778 seconds
Version 3: Key-value coding, using "self":
NSNumber *max=[numbers valueForKeyPath:@"@max.self"];
NSNumber *min=[numbers valueForKeyPath:@"@min.self"];
// 0.390 seconds
Version 4: Explicit loop:
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
Version 5: Block enumeration:
__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
The test program creates an array of 1000000 random numbers and then applies all sorting techniques to the same array. The timings above are the output of one run, but I make about 20 runs with very similar results in each run. I also changed the order in which the 5 sorting methods are applied to exclude caching effects.
Update: I have now created a (hopefully) better test program. The full source code is here: https://gist.github.com/anonymous/5356982. The average times for sorting an array of 1000000 random numbers are (in seconds, on an 3.1 GHz Core i5 iMac, release compile):
Sorting 1.404 KVO1 1.087 KVO2 0.367 Fast enum 0.017 Block enum 0.021
Update 2: As one can see, fast enumeration is faster than block enumeration (which is also stated here: http://blog.bignerdranch.com/2337-incremental-arrayification/).
EDIT: The following is completely wrong, because I forgot to initialize the object used as lock, as Hot Licks correctly noticed, so that no synchronization is done at all.
And with lock = [[NSObject alloc] init];
the concurrent enumeration is so slow
that I dare not to show the result. Perhaps a faster synchronization mechanism might
help ...)
This changes dramatically if you add the NSEnumerationConcurrent
option to the
block enumeration:
__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;
}
}];
The timing here is
Concurrent enum 0.009
so it is about twice as fast as fast enumeration. The result is probably not representative because it depends on the number of threads available. But interesting anyway! Note that I have used the "easiest-to-use" synchronization method, which might not be the fastest.
这篇关于找到NSNumbers的NSArray中最小和最大的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!