根据另一个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; }