Слияние 2d массивов - PullRequest
       4

Слияние 2d массивов

3 голосов
/ 21 февраля 2011

Предположим, у меня есть два массива:

arrayOne = [["james", 35], ["michael", 28], ["steven", 23], 
            ["jack", 18], ["robert", 12]]
arrayTwo = [["charles", 45], ["james",  36], ["trevor", 24], 
            ["michael", 17], ["steven", 4]]

Я хочу объединить их, чтобы у меня был один двумерный массив, где первым элементом каждого внутреннего массива является имя (james, charles,так далее).Вторым элементом внутреннего массива является его соответствующее значение в arrayOne, и если нет соответствующего значения, оно будет равно 0. Обратно для третьего элемента.Порядок не имеет значения, если числа совпадают с именем.Другими словами, я хотел бы получить что-то вроде этого

arrayResult = [["james", 35, 36], ["michael", 28, 17], ["steven", 23, 4],
               ["jack", 18, 0], ["robert", 12, 0], ["charles", 0, 45],
               ["trevor", 0, 4]]

Кроме того, я пытаюсь сделать так, чтобы я мог добавить больше «столбцов» к этому результату массива, если бы я дал другой массив.

Ответы [ 2 ]

4 голосов
/ 21 февраля 2011

Похоже, что вам действительно нужны словари, а не массивы. Если вы используете словарь, эта проблема становится намного проще. Преобразование в диктовку не может быть проще:

dictOne = dict(arrayOne)
dictTwo = dict(arrayTwo)

Оттуда вы можете соединить их так:

combined = dict()
for name in set(dictOne.keys() + dictTwo.keys()):
  combined[name] = [ dictOne.get(name, 0), dictTwo.get(name, 0) ]

Это создает новый словарь под названием combined, в который мы поместим окончательные данные. Затем мы создадим набор ключей из обоих исходных словарей. Использование набора гарантирует, что мы ничего не делаем дважды. Наконец, мы перебираем этот набор ключей и добавляем каждую пару значений в словарь combined, сообщая о вызовах метода .get для предоставления 0, если значение отсутствует. Если вам нужно переключить объединенный словарь обратно в массив, это тоже довольно просто:

arrayResult = []
for name in combined:
  arrayResult.append([ name ] + combined[name])

Предположим, что вы хотите добавить еще один столбец в свой словарь результатов, все, что вам нужно сделать, это изменить средний код, чтобы он выглядел так:

combined = dict()
for name in set(dictOne.keys() + dictTwo.keys() + dictThree.keys()):
  combined[name] = [ dictOne.get(name, 0), dictTwo.get(name, 0), dictThree.get(name, 0) ]

Если вы хотите инкапсулировать всю эту логику в функцию (что я бы порекомендовал), вы можете сделать это следующим образом:

def combine(*args):
  # Create a list of dictionaries from the arrays we passed in, since we are
  # going to use dictionaries to solve the problem.
  dicts = [ dict(a) for a in args ]

  # Create a list of names by looping through all dictionaries, and through all
  # the names in each dictionary, adding to a master list of names
  names = []
  for d in dicts:
    for name in d.keys():
      names.append(name)

  # Remove duplicates in our list of names by making it a set
  names = set(names)

  # Create a result dict to store results in
  result = dict()

  # Loop through all the names, and add a row for each name, pulling data from
  # each dict we created in the beginning
  for name in names:
    result[name] = [ d.get(name, 0) for d in dicts ]

  # Return, secure in the knowledge of a job well done. :-)
  return result

# Use the function:
resultDict = combine(arrayOne, arrayTwo, arrayThree)
4 голосов
/ 21 февраля 2011
>>> dict1 = dict(arrayOne)
>>> dict2 = dict(arrayTwo)
>>> keyset = set(dict1.keys() + dict2.keys())
>>> [[key, dict1.get(key, 0), dict2.get(key, 0)] for key in keyset]
[['james', 35, 36], ['robert', 12, 0], ['charles', 0, 45], 
 ['michael', 28, 17], ['trevor', 0, 24], ['jack', 18, 0], 
 ['steven', 23, 4]]

Это становится немного сложнее, если вы хотите добавить несколько столбцов;тогда словарь самый лучший.Но наличие 0 s в нужных местах становится проблемой, потому что, когда мы добавляем имя в «основной словарь», мы должны убедиться, что оно начинается со списка 0 s правильной длины.Я испытываю желание создать новый класс для этого, но сначала вот базовое решение на основе функций:

def add_column(masterdict, arr):
    mdlen = len(masterdict[masterdict.keys()[0]])
    newdict = dict(arr)
    keyset = set(masterdict.keys() + newdict.keys())
    for key in keyset:
        if key not in masterdict:
            masterdict[key] = [0] * mdlen
        masterdict[key].append(newdict.get(key, 0))

arrayOne =   [["james", 35],
              ["michael", 28],
              ["steven", 23],
              ["jack", 18],
              ["robert", 12]]
arrayTwo =   [["charles", 45],
              ["james",  36],
              ["trevor", 24],
              ["michael", 17],
              ["steven", 4]]
arrayThree = [["olliver", 11],
              ["james",  39],
              ["john", 22],
              ["michael", 13],
              ["steven", 6]]

masterdict = dict([(i[0], [i[1]]) for i in arrayOne])

add_column(masterdict, arrayTwo)
print masterdict
add_column(masterdict, arrayThree)
print masterdict

Вывод:

{'james': [35, 36], 'robert': [12, 0], 'charles': [0, 45], 
 'michael': [28, 17], 'trevor': [0, 24], 'jack': [18, 0], 
 'steven': [23, 4]}
{'james': [35, 36, 39], 'robert': [12, 0, 0], 'charles': [0, 45, 0], 
  'michael': [28, 17, 13], 'trevor': [0, 24, 0], 'olliver': [0, 0, 11], 
  'jack': [18, 0, 0], 'steven': [23, 4, 6], 'john': [0, 0, 22]}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...