2013-08-26 3 views
0

У меня есть два NSMutable Arrays (по меньшей мере 5000 записей), которые я хотел бы объединить в один массив/словарь. Оба массива имеют общий ключ => значение. Я бы хотел, чтобы один массив содержал ключи/значения из обоих массивов. Я видел несколько примеров в 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 
    } 
} 

Спасибо за ваши советы :)

ответ

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]; 

наконец ...

Если по вашему вопросу вы заранее знаете, что ваши данные отсортированы и что между соответствующими объектами массива существует взаимно однозначное соответствие, вы можете упростить:

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

Большое спасибо за очень информативный и пошаговый ответ! Извините, я получаю сообщение об ошибке «Ожидаемое выражение», когда я пытаюсь использовать последний параметр. Ошибка находится в строке [arrayA enumerateObjectsUsingBlock: { Есть ли ошибка в синтаксисе? – user2716667

+0

@ user2716667 - да, было несколько ошибок ... посторонний '{' on line 1 и отсутствующий '' 'в строке 4. Исправлено. – foundry

+0

Вы правы, два массива имеют точно такое же количество элементов. – user2716667

Смежные вопросы