【问题标题】:Joining two arrays of objects on a common key在一个公共键上连接两个对象数组
【发布时间】:2013-08-27 05:37:36
【问题描述】:

我有两个 NSMutable 数组(每个至少 5,000 条记录),我想将它们加入到单个数组/字典中。两个数组都有一个共同的 key=>value。我想要一个包含两个数组的键/值的数组。我在 PHP 中看到了一些示例(参见 Joining two multidimensional arrays using common array value),但我正在寻找 Objective C 解决方案。

NSMutableArray #1:
{
    [0] => NSObject
    {
        [itemID] => 221
        [Name] => "Adam"
    }
    [1] => NSObject
    {
        [itemID] => 7
        [Name] => "Jacob"
    }
}

NSMutableArray #2:
{
    [0] => NSObject
    {
        [itemID] => 221
        [location] => floor 1
        [room] => 56
    }

    [1] => NSObject
    {
        [itemID] => 7
        [location] => floor 2
        [room] => 12
    }
}

我在寻找什么:

NSMutableArray
{
    [0] => NSObject
    {
        [itemID] => 221
        [Name] => "Adam"
        [location] => floor 1
        [room] => 56
    }

    [1] => NSObject
    {
        [itemID] => 7
        [Name] => "Jacob" 
        [location] => floor 2
        [room] => 12
    }
}

感谢您的建议:)

【问题讨论】:

    标签: objective-c nsmutablearray nsdictionary


    【解决方案1】:

    这不是最有效的,但应该可以...

      NSMutableArray* result = [[NSMutableArray alloc] init];
      for (NSDictionary* dict1 in array1) {
        for (NSDictionary* dict2 in array2) {
          if ([[dict1 objectForKey:@"itemID"] isEqual:
              [dict2 objectForKey:@"itemID"]]) {
                 NSMutableDictionary* dict = [dict1 mutableCopy];
                 [dict addEntriesFromDictionary:dict2];
                 [result addObject: dict];
                 break;
              }
        }
      }
    

    更新

    这里有一些提高效率的客观 C 方法...

    (1) 在比较之前对数组进行排序:

    - (NSArray*)sortArray:(NSArray*)array {
        NSArray* sortDescriptors = 
             @[[[NSSortDescriptor alloc] initWithKey:@"itemID" 
                                           ascending:YES]];
        NSArray* result = [array sortedArrayUsingDescriptors:sortDescriptors];
        return result;
    }
    

    (2) 反向遍历您的字典。然后在匹配时删除内部数组的末尾(考虑到数组已排序,这是合理的,并且从数组末尾删除对象应该比从开头删除更有效)。

    for (NSDictionary* dict1 in [sortedArray1 reverseObjectEnumerator]) {
        for (NSDictionary* dict2 in [sortedArray2 reverseObjectEnumerator]) {
            if ([[dict1 objectForKey:@"itemID"] isEqual:
                 [dict2 objectForKey:@"itemID"]]) {
                    NSMutableDictionary* dict = [dict1 mutableCopy];
                    [dict addEntriesFromDictionary:dict2];
                    [result addObject: dict];
                    NSUInteger idx = [sortedArray2 indexOfObject:dict2];
                    NSRange range= NSMakeRange(idx, sortedArray2.count-1-idx);
                    [sortedArray2 removeObjectsInRange:range];
                    break;
            }
        }
    }
    

    (3) 使用基于块的快速枚举:

    [sortedArray1 enumerateObjectsWithOptions:NSEnumerationReverse
                                   usingBlock:
         ^(NSDictionary* dict1, NSUInteger idx, BOOL *stop) {
             [sortedArray2 enumerateObjectsWithOptions:NSEnumerationReverse
                                            usingBlock:
              ^(NSDictionary* dict2, NSUInteger jdx, BOOL *stop) {
                  if ([[dict1 objectForKey:@"itemID"] isEqual:
                       [dict2 objectForKey:@"itemID"]]) {
                          NSMutableDictionary* dict = [dict1 mutableCopy];
                          [dict addEntriesFromDictionary:dict2];
                          [result addObject: dict];
                          NSRange range= NSMakeRange(jdx, sortedArray2.count-1-jdx);
                          [sortedArray2 removeObjectsInRange:range];
                          *stop = YES;
                  }
              }];
         }];
    

    (2)和(3)之间的计算差异可能可以忽略不计,但是(3)的优点是每次迭代都传入索引和对象,而在(2)中你需要使用@获取索引987654325@.

    如果您确定每个数组具有相同的比较键值集,则可以省去NSRange 并将内部数组归约简化为:

    [sortedArray2 removeLastObject];
    

    终于...

    如果如您的问题所暗示的那样,您事先知道您的数据已排序并且各个数组对象之间存在一一对应关系,则可以简化:

    [arrayA enumerateObjectsUsingBlock:
        ^(NSDictionary* dict, NSUInteger idx, BOOL *stop) {
            NSMutableDictionary* mutableDict = [dict mutableCopy];
            [mutableDict addEntriesFromDictionary:arrayB[idx]];
             [result addObject:mutableDict];
        }];
    

    【讨论】:

    • 非常感谢您提供的信息丰富且一步一步的回答!抱歉,当我尝试使用最后一个选项时,出现“预期表达式”错误。错误就在[arrayA enumerateObjectsUsingBlock:{语法有错误吗?
    • @user2716667 - 是的,有几个错误......第 1 行有一个无关的{,第 4 行有一个缺少的]。现在已修复。
    • 你是对的,两个数组的项数完全相同。
    • ...所以如果你能正确地对它们进行排序并且你确定arrayA[i] 将与arrayB[i] 合并,那么最后一段代码就足够了。
    • @user2716667 - 我刚刚对“finally..”代码的第 4 行做了一个小的改进......你可以用数组文字语法 arrayB[idx] 替换旧式的 [arrayB objectAtIndex:idx] 跨度>
    猜你喜欢
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-28
    • 1970-01-01
    • 2019-01-06
    相关资源
    最近更新 更多