根据另一个NSArray字符串的排序对自定义对象的NSArray进行排序

Nic*_*ard 7 objective-c nsmutablearray nsarray ios

我有两个NSArray对象,我想要排序相同.一个包含NSString对象,另一个包含自定义Attribute对象.这是我的"关键"NSArray的样子:

// The master order
NSArray *stringOrder = [NSArray arrayWithObjects:@"12", @"10", @"2", nil];
Run Code Online (Sandbox Code Playgroud)

带有自定义对象的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];
Run Code Online (Sandbox Code Playgroud)

所以,我想要做的是使用stringOrder数组来确定items自定义对象数组的排序.我怎样才能做到这一点?

cwe*_*ung 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])]
}];
Run Code Online (Sandbox Code Playgroud)

或者没有ObjC文字:

[items sortUsingComparator:^NSComparisonResult(Attribute *obj1, Attribute *obj2) {
    return [[NSNumber numberWithInt:[stringOrder indexOfObject:obj1.assetID]] compare:[NSNumber numberWithInt:[stringOrder indexOfObject:obj2.assetID]]]
}];
Run Code Online (Sandbox Code Playgroud)

  • 由于在每次比较时调用`indexOfObject`(线性搜索)会将排序减少到O(n²),因此这会产生严重的性能影响.你最好压缩数组并对结果进行排序,甚至从assetIds创建一个字典到另一个数组中的索引 (2认同)

Nik*_*jic 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]];
Run Code Online (Sandbox Code Playgroud)

对照

以下是在iPhone 5上运行这两种方法的结果:

sortUsingComparator:

100  - 0.012 s
1000 - 1.116 s
2000 - 4.405 s
3000 - 9.028 s
Run Code Online (Sandbox Code Playgroud)

预填充阵列

100 -  0.003 s
1000 - 0.236 s
2000 - 0.917 s
3000 - 2.063 s
Run Code Online (Sandbox Code Playgroud)