How can I reverse a NSArray in Objective-C?
There is a much easier solution, if you take advantage of the built-in reverseObjectEnumerator
method on NSArray
, and the allObjects
method of NSEnumerator
:
NSArray* reversedArray = [[startArray reverseObjectEnumerator] allObjects];
allObjects
is documented as returning an array with the objects that have not yet been traversed with nextObject
, in order:
This array contains all the remaining objects of the enumerator in enumerated order.
For obtaining a reversed copy of an array, look at danielpunkass' solution using reverseObjectEnumerator
.
For reversing a mutable array, you can add the following category to your code:
@implementation NSMutableArray (Reverse)- (void)reverse { if ([self count] <= 1) return; NSUInteger i = 0; NSUInteger j = [self count] - 1; while (i < j) { [self exchangeObjectAtIndex:i withObjectAtIndex:j]; i++; j--; }}@end
Some benchmarks
1. reverseObjectEnumerator allObjects
This is the fastest method:
NSArray *anArray = @[@"aa", @"ab", @"ac", @"ad", @"ae", @"af", @"ag", @"ah", @"ai", @"aj", @"ak", @"al", @"am", @"an", @"ao", @"ap", @"aq", @"ar", @"as", @"at", @"au", @"av", @"aw", @"ax", @"ay", @"az", @"ba", @"bb", @"bc", @"bd", @"bf", @"bg", @"bh", @"bi", @"bj", @"bk", @"bl", @"bm", @"bn", @"bo", @"bp", @"bq", @"br", @"bs", @"bt", @"bu", @"bv", @"bw", @"bx", @"by", @"bz", @"ca", @"cb", @"cc", @"cd", @"ce", @"cf", @"cg", @"ch", @"ci", @"cj", @"ck", @"cl", @"cm", @"cn", @"co", @"cp", @"cq", @"cr", @"cs", @"ct", @"cu", @"cv", @"cw", @"cx", @"cy", @"cz"];NSDate *methodStart = [NSDate date];NSArray *reversed = [[anArray reverseObjectEnumerator] allObjects];NSDate *methodFinish = [NSDate date];NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];NSLog(@"executionTime = %f", executionTime);
Result: executionTime = 0.000026
2. Iterating over an reverseObjectEnumerator
This is between 1.5x and 2.5x slower:
NSDate *methodStart = [NSDate date];NSMutableArray *array = [NSMutableArray arrayWithCapacity:[anArray count]];NSEnumerator *enumerator = [anArray reverseObjectEnumerator];for (id element in enumerator) { [array addObject:element];}NSDate *methodFinish = [NSDate date];NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];NSLog(@"executionTime = %f", executionTime);
Result: executionTime = 0.000071
3. sortedArrayUsingComparator
This is between 30x and 40x slower (no surprises here):
NSDate *methodStart = [NSDate date];NSArray *reversed = [anArray sortedArrayUsingComparator: ^(id obj1, id obj2) { return [anArray indexOfObject:obj1] < [anArray indexOfObject:obj2] ? NSOrderedDescending : NSOrderedAscending;}];NSDate *methodFinish = [NSDate date];NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];NSLog(@"executionTime = %f", executionTime);
Result: executionTime = 0.001100
So [[anArray reverseObjectEnumerator] allObjects]
is the clear winner when it comes to speed and ease.