根据另一个NSArraystring的sorting对自定义对象的NSArray进行sorting
我有两个NSArray
对象,我想sorting相同。 一个包含NSString
对象,另一个是自定义的Attribute
对象。 这是什么我的“关键”NSArray看起来像:
// The master order NSArray *stringOrder = [NSArray arrayWithObjects:@"12", @"10", @"2", nil];
具有自定义对象的NSArray:
// The array of custom Attribute objects that I want sorted by the stringOrder array NSMutableArray *items = [[NSMutableArray alloc] init]; Attribute *attribute = nil; attribute = [[Attribute alloc] init]; attribute.assetID = @"10"; [items addObject:attribute]; attribute = [[Attribute alloc] init]; attribute.assetID = @"12"; [items addObject:attribute]; attribute = [[Attribute alloc] init]; attribute.assetID = @"2"; [items addObject:attribute];
所以,我想要做的是使用stringOrder
数组来确定自定义对象的items
数组的sorting。 我怎样才能做到这一点?
因此,我直接比较stringOrder中的obj1.assetID的索引和stringOrder中的obj2.assetID的索引(使用Objective-C文字@()来转换NSString => NSNumber)
[items sortUsingComparator:^NSComparisonResult(Attribute *obj1, Attribute *obj2) { return [@([stringOrder indexOfObject:obj1.assetID]) compare:@([stringOrder indexOfObject:obj2.assetID])] }];
或没有ObjC文字:
[items sortUsingComparator:^NSComparisonResult(Attribute *obj1, Attribute *obj2) { return [[NSNumber numberWithInt:[stringOrder indexOfObject:obj1.assetID]] compare:[NSNumber numberWithInt:[stringOrder indexOfObject:obj2.assetID]]] }];
虽然cwehrungs的答案将完成工作,但相对较小的arrays的性能并不好。
这是另一种执行相同种类的方法,虽然还很不完善,但速度更快一些:
NSMutableArray *sorted = [NSMutableArray array]; // pre-populate with objects for (int i = 0; i < stringOrder.count; i++) { [sorted addObject:[NSNull null]]; } // place the items at the correct position for (Attribute *a in items) { NSUInteger idx = [stringOrder indexOfObject:a.assetID]; if (idx != NSNotFound) { [sorted setObject:a atIndexedSubscript:idx]; } } // finally remove all the unecesarry placeholders if one array was smaller [sorted removeObject:[NSNull null]];
对照
以下是在iPhone 5上运行这两种方法的结果:
sortUsingComparator:
100 - 0.012 s 1000 - 1.116 s 2000 - 4.405 s 3000 - 9.028 s
预填充数组
100 - 0.003 s 1000 - 0.236 s 2000 - 0.917 s 3000 - 2.063 s
有几个方法可以采取。
您可以将您的Attribute对象存储在NSDictionary中,其中键是stringOrder数组中的string。 然后,你可以得到一个sorting的键数组,并使用它来填充你用来显示它们的任何视图:
NSArray* sortedKeys = [dict keysSortedByValueUsingComparator:^(id obj1, id obj2) { return [obj1 compareTo:obj2]; }
另一个是你将sorting顺序作为Attribute对象的内部属性,所以可以直接对一个Attributes数组进行sorting。 如果sorting顺序实际上是属性对象的内部属性,我只会build议采取这种方法。 如果不是这样,那么您将结束在不属于它的地方存储演示信息。
这是一个例子:
NSArray* sortedAttrs = [attributes sortedArrayUsingComparator:^(id obj1, id obj2) { // Perform comparison of Attribute's, ahem, attributes }
这是我提出的解决scheme,工作得非常好。 任何人都看到这个性能问题?
for (Attribute *a in items) { int index = [stringOrder indexOfObject:a.assetID]; a.sortOrder = index; } NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sortOrder" ascending:YES]; NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; NSArray *sortedArray = [items sortedArrayUsingDescriptors:sortDescriptors];
并行处理:
结果(四核):
1. sortme:95 sortby:852345 sorted:95 time:0.052576 2. sortme:54248 sortby:852345 sorted:54243 time:0.264660 -(NSArray *)sortArray:(NSArray *)sortme sortBy:(NSArray *)sortBy{ CFAbsoluteTime time = CFAbsoluteTimeGetCurrent(); NSSet *sortmeSet = [NSSet setWithArray:sortme]; NSMutableDictionary *sortDictionary = [NSMutableDictionary dictionary]; dispatch_queue_t sortDictionaryThread = dispatch_queue_create("my.sortDictionaryThread", DISPATCH_QUEUE_CONCURRENT); [sortBy enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([sortmeSet containsObject:obj]){ dispatch_barrier_async(sortDictionaryThread, ^{ sortDictionary[obj] = @(idx); }); } }]; __block NSArray *sortedArray = nil; dispatch_barrier_sync(sortDictionaryThread, ^{ sortedArray = [sortDictionary keysSortedByValueUsingSelector:@selector(compare:)]; }); NSLog(@"sortme:%li sortby:%li sorted:%li time:%f",sortme.count,sortBy.count,sortedArray.count, CFAbsoluteTimeGetCurrent() - time); return sortedArray; }