Python-合并两个字典列表,只返回第二个列表中的最后一个字典

5

我试着在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
您的代码有误。对于l3中的每个字典,您更新了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
这个应该可以用一行代码搞定:

# 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

你的第一个问题在这里:

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

你正在复制第一个列表中所有字典的引用。它们与第一个列表中的相同。这意味着,编辑一个字典(例如使用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)

这里你在两个字典上循环。 l3l1 的一个副本,对于该列表中的每个项目,您都会使用来自l2中每个项目的数据进行更新。 字典必须具有唯一键,因此每次更新键ab时,它都会覆盖先前的值。

然后您基本上以不同的顺序执行相同的操作。

您想要做的是同时迭代每个列表中的字典,并从每个字典中的数据创建新字典。 列表中每个位置的字典都具有唯一键,因此不会有任何覆盖。

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})]

所以一旦你有了那个,就从源字典创建一个新的字典。正如你所知道的{}是一个新字典的语法,对变量执行**意味着提取项目(键/值对)并将它们插入到新字典中。

另一种不太Pythonic但对于新手来说可能更容易编写的方法是这样的:

l3 = []

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

我希望你能欣赏第一个解决方案的简洁性。


谢谢 - 我也感谢你的解释! - bouvetIsle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接