【问题标题】:Pyhon - merging two list of dictionaries, only last dictionary in the second list returnedPython - 合并两个字典列表,仅返回第二个列表中的最后一个字典
【发布时间】:2020-07-31 06:45:49
【问题描述】:

我尝试在 SO 中进行一些搜索以找到解决方案,但我仍然感到困惑。我认为我从根本上误解了循环、列表和字典。

我基本上是自学成才,绝不是专家,所以如果这是一个非常愚蠢的问题,请提前道歉。

我有各种字典列表,例如下面 sn-p 中的 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}]

这就是我所拥有的(cmets 解释我认为代码是/应该做什么)

# 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() 并最终得到一个字典元组列表,这让我觉得我要么使用不正确,要么它对于我需要的工具来说太复杂了。 根据我在做一些研究时的理解,问题是我一直在覆盖我刚刚写的值,我认为这就是为什么我总是最终只在任何地方添加最后一个值。

任何帮助表示赞赏!

【问题讨论】:

    标签: python list loops dictionary


    【解决方案1】:

    你的第一个问题在这里:

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

    您正在将 references 复制到第一个列表中的所有字典。它们与您的第一个列表中的相同。这意味着,编辑 dict(例如调用 update())将影响 both 列表。

    # 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)
    

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

    【讨论】:

    • 谢谢 - 我也感谢您的解释!
    【解决方案2】:

    这应该可以在一行代码中解决问题:

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

    【讨论】:

      【解决方案3】:

      您的代码不正确。对于 l3 中的每个 dict,您更新 l2 中的每个 dict。

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

      【讨论】:

        猜你喜欢
        • 2013-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多