0

単一の配列/辞書に結合したい 2 つの NSMutable 配列 (それぞれ少なくとも 5,000 レコード) があります。両方の配列に共通のキー=>値があります。両方の配列のキー/値を含む単一の配列が必要です。PHP でいくつかの例を見てきましたが (共通の配列値を使用して 2 つの多次元配列を結合するを参照)、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
    }
}

アドバイスありがとうございます:)

4

1 に答える 1

2

これは最も効率的ではありませんが、うまくいくはずです...

  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) では を使用してインデックスを取得する必要がありますindexOfObject

各配列に同じ比較キー値のセットが含まれていることが確実な場合はNSRange、内部配列の縮小を省いて単純化して 、次のようにすることができます。

[sortedArray2 removeLastObject];

最後に...

質問が示唆するように、データがソートされており、それぞれの配列オブジェクト間に 1 対 1 の対応があることが事前にわかっている場合は、次のように簡略化できます。

[arrayA enumerateObjectsUsingBlock:
    ^(NSDictionary* dict, NSUInteger idx, BOOL *stop) {
        NSMutableDictionary* mutableDict = [dict mutableCopy];
        [mutableDict addEntriesFromDictionary:arrayB[idx]];
         [result addObject:mutableDict];
    }];
于 2013-08-26T04:02:28.323 に答える