我有两个NSArray
个对象,我希望对它们进行相同的排序。一个包含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
自定义对象数组的排序。
我该怎么做?
答案 0 :(得分:14)
在此,我直接将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]]]
}];
答案 1 :(得分:6)
虽然cwehrungs的答案将完成工作,但在相对较小的阵列上性能并不高。
这是另一种执行相同类型排序的方法,但速度要快一些(但仍然远非完美):
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
答案 2 :(得分:2)
您可以采取几种方法。
您可以将属性对象存储在NSDictionary中,其中键是stringOrder数组中的字符串。然后,您可以获得一个已排序的键数组,并使用它来填充您用于显示它们的任何视图:
NSArray* sortedKeys = [dict keysSortedByValueUsingComparator:^(id obj1, id obj2) {
return [obj1 compareTo:obj2];
}
另一个是您将排序顺序作为Attribute对象的固有属性,因此可以直接对Attributes数组进行排序。如果排序顺序实际上是Attributes对象的固有属性,我只建议采用这种方法。如果不是,并且你这样做,你将最终存储不属于它的演示信息。
以下是一个例子:
NSArray* sortedAttrs = [attributes sortedArrayUsingComparator:^(id obj1, id obj2) {
// Perform comparison of Attribute's, ahem, attributes
}
答案 3 :(得分:1)
我提出的解决方案非常有效。有人看到这方面的性能问题吗?
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];
答案 4 :(得分:0)
并行处理:
结果(四核):
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;
}