【问题标题】:Sorting two NSArrays together side by side将两个 NSArray 并排排序
【发布时间】:2012-09-08 08:25:36
【问题描述】:

我有几个需要并排排序的数组。

例如,第一个数组的名称为:@[@"Joe", @"Anna", @"Michael", @"Kim"],并且 另一个数组保存地址:@[@"Hollywood bld", @"Some street 3", @"That other street", @"country road"],数组的索引放在一起。 “乔”住在“好莱坞大厦”等等。

我想按字母顺序对名称数组进行排序,然后将地址数组排在旁边,以便它们仍然在一起,“Hollywood bld”与“Joe”具有相同的索引。我知道如何使用

对一个数组按字母顺序排序
NSSortDescriptor *sort=[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO];
[myArray sortUsingDescriptors:[NSArray arrayWithObject:sort]];

但是有什么简单的方法可以让第二个数组按照适当的顺序排序吗?

【问题讨论】:

标签: objective-c arrays cocoa cocoa-touch sorting


【解决方案1】:
  1. 创建一个排列数组,初始设置为p[i]=i
  2. 根据第一个数组的name键对排列进行排序
  3. 使用排列对两个数组重新排序

示例:假设第一个数组是{"quick", "brown", "fox"}。排列以{0, 1, 2} 开始,排序后变为{1, 2, 0}。现在您可以遍历排列数组,并根据需要重新排序原始数组和第二个数组。

NSArray *first = [NSArray arrayWithObjects: @"quick", @"brown", @"fox", @"jumps", nil];
NSArray *second = [NSArray arrayWithObjects: @"jack", @"loves", @"my", @"sphinx", nil];
NSMutableArray *p = [NSMutableArray arrayWithCapacity:first.count];
for (NSUInteger i = 0 ; i != first.count ; i++) {
    [p addObject:[NSNumber numberWithInteger:i]];
}
[p sortWithOptions:0 usingComparator:^NSComparisonResult(id obj1, id obj2) {
    // Modify this to use [first objectAtIndex:[obj1 intValue]].name property
    NSString *lhs = [first objectAtIndex:[obj1 intValue]];
    // Same goes for the next line: use the name
    NSString *rhs = [first objectAtIndex:[obj2 intValue]];
    return [lhs compare:rhs];
}];
NSMutableArray *sortedFirst = [NSMutableArray arrayWithCapacity:first.count];
NSMutableArray *sortedSecond = [NSMutableArray arrayWithCapacity:first.count];
[p enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSUInteger pos = [obj intValue];
    [sortedFirst addObject:[first objectAtIndex:pos]];
    [sortedSecond addObject:[second objectAtIndex:pos]];
}];
NSLog(@"%@", sortedFirst);
NSLog(@"%@", sortedSecond);

【讨论】:

    【解决方案2】:

    首先,您可能需要重新考虑一种架构,该架构要求您像这样以并行方式对两个数组进行排序。但话虽如此,您可以通过创建一个临时字典数组来保持两个数组的元素成对。

    然后你对合并后的数组进行排序,再次提取两个数组,按要求排序:

    原始数据:

    NSArray *names     = @[@"Joe", @"Anna", @"Michael"];
    NSArray *addresses = @[@"Hollywood bld", @"Some street 3", @"That other street"];
    

    实际排序代码:

    NSMutableArray *combined = [NSMutableArray array];
    
    for (NSUInteger i = 0; i < names.count; i++) {
        [combined addObject: @{@"name" : names[i], @"address": addresses[i]}];
    }
    
    [combined sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]];
    
    names     = [combined valueForKey:@"name"];
    addresses = [combined valueForKey:@"address"];
    

    请注意,valueForKey: 在数组上使用会提取一个大小相同的新数组,其中填充了原始数组中对象的属性。在这种情况下,它会根据原始数组创建新数组,并根据需要进行排序。

    这种方法只需要几行代码,并且在需要时易于遵循和调试。

    【讨论】:

    • 很好地使用-valueForKey:
    • 使用objectForKey 而不是valueForKey
    【解决方案3】:

    最好的方法是重组你的数据,让你只有一个数组。在您的示例中,最有意义的是创建一个具有名称和地址的新类,将它们放在一个数组中并按名称对其进行排序。

    【讨论】:

    • 或者只是创建一个字典数组,每个字典都包含一个名称和对应的地址。
    • 没错,虽然字典总是让我觉得有人不够关心他们的数据的用途,无法对其进行分类。 :-)
    【解决方案4】:

    您可以通过在排序前后跟踪对象的索引来做到这一点,但也许拥有一个拥有所有这些属性的对象会更容易

    Person : NSObject
    
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, copy) NSString *addresss;
    

    然后将这些对象存储到一个数组中,您可以按nameaddress 键路径排序

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-27
      • 1970-01-01
      • 1970-01-01
      • 2015-10-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多