我需要反转NSArray。
举个例子:
[1,2,3,4,5]必须变成:[5,4,3,2,1]
实现这一目标的最佳方式是什么?
我需要反转NSArray。
举个例子:
[1,2,3,4,5]必须变成:[5,4,3,2,1]
实现这一目标的最佳方式是什么?
当前回答
一些基准
1. reverseObjectEnumerator allObjects
这是最快的方法:
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);
结果:executionTime = 0.000026
2. 迭代一个reverseObjectEnumerator对象
这要慢1.5到2.5倍:
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);
结果:executionTime = 0.000071
3.sortedArrayUsingComparator
这要慢30到40倍(这里没有意外):
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);
结果:executionTime = 0.001100
因此,当谈到速度和易用性时,[[anArray reverseObjectEnumerator] allObjects显然是赢家。
其他回答
至于我,你考虑过数组是如何被填充的吗?我正在向一个数组中添加许多对象,并决定在开始时插入每个对象,将任何现有对象向上推一个。在这种情况下,需要一个可变数组。
NSMutableArray *myMutableArray = [[NSMutableArray alloc] initWithCapacity:1];
[myMutableArray insertObject:aNewObject atIndex:0];
Georg Schölly的分类非常好。然而,对于NSMutableArray,当数组为空时,使用NSUIntegers作为索引会导致崩溃。正确的代码是:
@implementation NSMutableArray (Reverse)
- (void)reverse {
NSInteger i = 0;
NSInteger j = [self count] - 1;
while (i < j) {
[self exchangeObjectAtIndex:i
withObjectAtIndex:j];
i++;
j--;
}
}
@end
试试这个:
for (int i = 0; i < [arr count]; i++)
{
NSString *str1 = [arr objectAtIndex:[arr count]-1];
[arr insertObject:str1 atIndex:i];
[arr removeObjectAtIndex:[arr count]-1];
}
要获得数组的反向副本,请参阅danielpunkass使用reverseObjectEnumerator的解决方案。
为了反转一个可变数组,你可以在你的代码中添加以下类别:
@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
在看了上面其他人的答案并在这里找到马特·加拉格尔的讨论后
我建议:
NSMutableArray * reverseArray = [NSMutableArray arrayWithCapacity:[myArray count]];
for (id element in [myArray reverseObjectEnumerator]) {
[reverseArray addObject:element];
}
正如Matt所观察到的:
在上面的例子中,你可能想知道-[NSArray reverseObjectEnumerator]是否会在循环的每次迭代中运行-可能会降低代码的速度。<…>
此后不久,他这样回答:
<……当for循环开始时,"collection"表达式只计算一次。这是最好的情况,因为您可以安全地将昂贵的函数放在“collection”表达式中,而不会影响循环的每次迭代性能。