Pyhon - объединяет два списка словарей, возвращается только последний словарь во втором списке - PullRequest
4 голосов
/ 17 апреля 2020

Я попытался выполнить небольшой поиск в SO, чтобы найти решение, но я все еще в тупике. Я думаю, что в корне неправильно понимаю кое-что о циклах, списках и словарях.

Я в основном самоучка и ни в коем случае не эксперт, поэтому заранее извиняюсь, если это невероятно глупый вопрос.

У меня есть различные списки словарей, например, образцы l1 и l2 во фрагменте ниже. Мой желаемый вывод - что-то вроде

l3 = [{'A':1, 'B':4},{'A':2,'B':5},{'A':3,'B':6}

Однако, независимо от того, что я пытаюсь, мне всегда кажется, что я получаю только последнюю пару ключ-значение из второго словаря, то есть

[{'A': 1, 'B': 6}, {'A': 2, 'B': 6}, {'A': 3, 'B': 6}]

Это то, что у меня есть (комментарии, чтобы объяснить, что я думаю, что код должен / должен делать)

# First list of dictionaries

l1 = [{'A': 1},{'A': 2},{'A': 3}]
print(l1)

# Second list of dictionaries
l2 = [{'B': 4},{'B': 5},{'B': 6}]
print(l2)

# Empty list - to receive dictionaries in l1 and l2
l3 =[]
print(l3)

# Adding dictionaries from l1 into l3
for dict1 in l1:
    l3.append(dict1)
print(l3)

# Opening l3 to loop through each dictionary, using range(len()) to loop through the index positions
for i in range(len(l3)):

    # Opening l2 to loop through each dictionary
    for dict2 in l2:
        l3[i].update(dict2)
print(l3)

# Tried inverting the lists here, looping through l2 and then looping through l3 to append all dictionaries in l2
for dict2 in l2:
    for i in range(len(l3)):
        l3[i].update(dict2)
print(l3)

Я также попытался использовать zip () и получил список кортежей словарей что заставляет меня думать, что я использую это неправильно, или это слишком сложный инструмент для того, что мне нужно здесь. Исходя из того, что я мог понять, проводя некоторые исследования, проблема в том, что я продолжаю переопределять только что написанные значения, я предполагаю, что поэтому я постоянно получаю только последнюю добавленную стоимость везде.

Любая помощь приветствуется!

Ответы [ 3 ]

3 голосов
/ 17 апреля 2020

Ваш код здесь неверный. Для каждого dict в l3 вы обновляете каждый отдельный dict в l2.

for i in range(len(l3)):

    # Opening l2 to loop through each dictionary
    for dict2 in l2:
        l3[i].update(dict2)

Попробуйте это:

for i in range(len(l3)):
    l3[i].update(l2[i])

Вот лучшее решение: значение второго словаря списка перезапишет первое, если они имеют одинаковый ключ.

result = list(map(lambda x,y:{**x, **y}, l1, l2))
1 голос
/ 17 апреля 2020

Это должно сделать трюк в одной строке кода:

# First list of dictionaries
l1 = [{'A': 1},{'A': 2},{'A': 3}]
print(l1)

# Second list of dictionaries
l2 = [{'B': 4},{'B': 5},{'B': 6}]
print(l2)

# add dictionaries for dictionaries in zipped list1 and list2
l3 = [dict(d1, **d2) for d1, d2 in zip(l1, l2) ]
print(l3)

Вывод:

[{'A': 1}, {'A': 2}, {'A': 3}]
[{'B': 4}, {'B': 5}, {'B': 6}]
[{'A': 1, 'B': 4}, {'A': 2, 'B': 5}, {'A': 3, 'B': 6}]
0 голосов
/ 17 апреля 2020

Ваша первая проблема здесь:

# Adding dictionaries from l1 into l3
for dict1 in l1:
    l3.append(dict1)
print(l3)

Вы копируете ссылки на все слова в первом списке. Они такие же, как в вашем первом списке. Это означает, что редактирование dict (как при вызове update()) повлияет на оба списков.

# Opening l3 to loop through each dictionary, using range(len()) to loop through the index positions
for i in range(len(l3)):

    # Opening l2 to loop through each dictionary
    for dict2 in l2:
        l3[i].update(dict2)
print(l3)

# Tried inverting the lists here, looping through l2 and then looping through l3 to append all dictionaries in l2
for dict2 in l2:
    for i in range(len(l3)):
        l3[i].update(dict2)
print(l3)

Здесь вы дважды просматриваете диктовки. l3 является копией l1, и для каждого элемента в этом списке вы обновляете его данными каждого элементов в l2. У Dicts должны быть уникальные ключи, поэтому каждый раз, когда вы обновляете ключи a и b, он перезаписывает предыдущие значения.

Тогда вы в основном делаете то же самое, но в другом порядке.

Что Вы хотите сделать это, повторяя указания в каждом списке одновременно, и создавая новые указания из данных в каждом. У точек в каждом месте списка есть уникальные ключи, поэтому перезаписи не будет.

l3 = [{**d1, **d2} for d1, d2 in zip(l1, l2)]

zip() - правильная функция для использования здесь. Он берет по одному предмету из каждого списка и передает их вам в паре. Предмет в позиции i в одном и другом списке.

>>> print(list(zip(l1, l2)))
[({'A': 1}, {'B': 4}), ({'A': 2}, {'B': 5}), ({'A': 3}, {'B': 6})]

Так что, как только вы это сделаете, создайте новый диктат из исходных диктов. Как вы знаете, {} является синтаксисом для нового dict, а выполнение ** для переменной означает извлечение элементов (пар ключ / значение) и вставку их в новый dict.

Другой, менее pythoni c, но, возможно, проще для нового ie способа написать это было бы так:

l3 = []

for d1, d2 in zip(l1, l2):
  d3 = {}
  d3.update(d1)
  d3.update(d2)
  l3.append(d3)

Надеюсь, вы сможете оценить краткость первого решения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...