ios 在 NSNumbers 的 NSArray 中查找最小值和最大值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15931112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Finding smallest and biggest value in NSArray of NSNumbers
提问by Sergey Grischyov
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?
什么是比较所有值的有效和伟大的方式NSArray
,包含NSNumbers
从floats
找到的最大一个和最小的一个?
Any ideas how to do this nice and quick in Objective-C?
任何想法如何在Objective-C 中做到这一点又好又快?
回答by Martin R
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:
如果执行速度(而不是编程速度)很重要,那么显式循环是最快的。我使用 1000000 个随机数的数组进行了以下测试:
Version 1: sort the array:
版本 1:对数组进行排序:
NSArray *sorted1 = [numbers sortedArrayUsingSelector:@selector(compare:)];
// 1.585 seconds
Version 2: Key-value coding, using "doubleValue":
版本 2:键值编码,使用“doubleValue”:
NSNumber *max=[numbers valueForKeyPath:@"@max.doubleValue"];
NSNumber *min=[numbers valueForKeyPath:@"@min.doubleValue"];
// 0.778 seconds
Version 3: Key-value coding, using "self":
版本 3:键值编码,使用“self”:
NSNumber *max=[numbers valueForKeyPath:@"@max.self"];
NSNumber *min=[numbers valueForKeyPath:@"@min.self"];
// 0.390 seconds
Version 4: Explicit loop:
版本 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
Version 5: Block enumeration:
版本 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
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.
测试程序创建一个包含 1000000 个随机数的数组,然后将所有排序技术应用于同一个数组。上面的计时是一次运行的输出,但我进行了大约 20 次运行,每次运行的结果都非常相似。我还更改了应用 5 种排序方法以排除缓存效果的顺序。
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):
更新:我现在已经创建了一个(希望)更好的测试程序。完整的源代码在这里:https: //gist.github.com/anonymous/5356982。对 1000000 个随机数数组进行排序的平均时间为(以秒为单位,在 3.1 GHz Core i5 iMac 上,发布编译):
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/).
更新 2:正如人们所看到的,快速枚举比块枚举更快(这里也有说明: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 slowthat I dare not to show the result. Perhaps a faster synchronization mechanism might
help ...)
编辑:以下是完全错误的,因为我忘记初始化用作锁的对象,正如 Hot Licks 正确注意到的那样,因此根本没有进行同步。而且lock = [[NSObject alloc] init];
并发枚举太慢了,我不敢展示结果。也许更快的同步机制可能会有所帮助...)
This changes dramatically if you add the NSEnumerationConcurrent
option to the
block enumeration:
如果您将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;
}
}];
The timing here is
Concurrent enum 0.009
__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
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.
所以它的速度大约是快速枚举的两倍。结果可能不具有代表性,因为它取决于可用线程的数量。但无论如何都很有趣!请注意,我使用了“最容易使用”的同步方法,这可能不是最快的。
回答by Anoop Vaidya
Save float by wrapping under NSNumber then
通过在 NSNumber 下包装来保存浮点数然后
NSNumber *max=[numberArray valueForKeyPath:@"@max.doubleValue"];
NSNumber *min=[numberArray valueForKeyPath:@"@min.doubleValue"];
*Not compiled and checked, already checked with intValue, not sure about double or float
*没有编译和检查,已经用 intValue 检查过,不确定是 double 还是 float
回答by vikingosegundo
sort it. take the first and the last element.
把它分类。取第一个和最后一个元素。
btw: you cant store floats in an NSArray, you will need to wrap them in NSNumber objects.
顺便说一句:您不能将浮点数存储在 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];
回答by JonahGabriel
I agree with sorting the array then picking the first and last elements, but I find this solution more elegant (this will also work for non numeric objects by changing the comparison inside the block):
我同意对数组进行排序然后选择第一个和最后一个元素,但我发现这个解决方案更优雅(通过更改块内的比较,这也适用于非数字对象):
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];
}];
If you really want to get fancy and have a really long list and you don't want to block your main thread, this should work:
如果你真的想要花哨并且有一个很长的列表并且你不想阻塞你的主线程,这应该有效:
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);
回答by Frank
Made simple
变得简单
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);