Finding smallest and biggest value in NSArray of NSNumbers
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 sortingtechniques 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 anarray of 1000000 random numbers are (in seconds, on an 3.1 GHz Core i5 iMac, release compile):
Sorting 1.404KVO1 1.087KVO2 0.367Fast enum 0.017Block 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 slowthat I dare not to show the result. Perhaps a faster synchronization mechanism mighthelp ...)
This changes dramatically if you add the NSEnumerationConcurrent
option to theblock 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 representativebecause it depends on the number of threads available. But interesting anyway! Note that Ihave used the "easiest-to-use" synchronization method, which might not be the fastest.
Save float by wrapping under NSNumber then
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
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 *numbers = @[@2.1, @8.1, @5.0, @.3];numbers = [numbers sortedArrayUsingSelector:@selector(compare:)];float min = [numbers[0] floatValue];float max = [[numbers lastObject] floatValue];