如果您只需要对象出现的次数,那么库尔特的答案就很好了。但是,如果您确实需要分块,则应该可以:
NSArray *original = @[@1, @3, @5, @7, @9, @8, @5, @3, @2, @4, @3, @6];
NSMutableArray *chunked = [NSMutableArray array];
NSNumber *current = nil;
for (NSNumber *number in [original sortedArrayUsingSelector:@selector(compare:)]) {
if (![number isEqual:current]) {
[chunked addObject:[NSMutableArray arrayWithObject:number]];
current = number;
} else {
[[chunked lastObject] addObject:number];
}
}
NSLog(@"%@", chunked);
除非我遗漏了什么,否则这在计算上并不复杂,并且应该比 Tim 的原始方法更有效(不需要字典、集合或散列)。涉及一种排序(在快速枚举中,容器 - 之后的部分in
- 仅评估一次),并且您迭代排序数组一次。NSMutableArray
插入O(1)
在任一端,所以最坏的情况应该是O(n)
因为迭代。
实际上:经过进一步审查,以下代码对于大量数字的运行速度要快得多。它稍微复杂一些,但运行效率更高。
NSArray *original = @[@1, @3, @5, @7, @9, @8, @5, @3, @2, @4, @3, @6];
NSMutableArray *chunked = [NSMutableArray array];
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:original];
for (NSNumber *number in countedSet) {
NSMutableArray *chunk = [NSMutableArray array];
NSUInteger count = [set countForObject:number];
for (NSUInteger i = 0; i < count; i++) {
[chunk addObject:number];
}
[chunked addObject:chunk];
}
[chunked sortUsingComparator:^(NSArray *a1, NSArray *a2) {
return [a1[0] compare:a2[0]];
}];
NSLog(@"%@", chunked);
使用10000000
随机数,第一个实现大约在几12.27
秒钟内运行,而第二个实现在0.92
几秒钟内运行。去搞清楚。
第二种方法的缺点是它创建的块都是同一个对象的副本。如果这给您带来了问题(在一般情况下,内存管理可能有问题,或者如果您的对象在某种意义上可以被认为是“平等的”,即使它们的所有属性都不完全如此),那么使用第一个方法。否则,这对你会更好。
补充说明:进一步思考,我知道这两种方法之间的时间差异有些可疑,我是对的。如果您的数据集有很多变化(重复数字很少),方法 2 的运行速度会慢得多;数字的变化对方法 1 的影响不大。对于许多重复的数字,方法 2 会很快,但如果您的数据集是完全随机的,您最好使用方法 1。
这是我用来测试这两个的代码:http: //pastebin.com/9syEyiyM