合并几个python词典

jer*_*use 38 python merge dictionary

我必须合并python字典列表.例如:

dicts[0] = {'a':1, 'b':2, 'c':3}
dicts[1] = {'a':1, 'd':2, 'c':'foo'}
dicts[2] = {'e':57,'c':3}

super_dict = {'a':[1], 'b':[2], 'c':[3,'foo'], 'd':[2], 'e':[57]}    
Run Code Online (Sandbox Code Playgroud)

我写了以下代码:

super_dict = {}
for d in dicts:
    for k, v in d.items():
        if super_dict.get(k) is None:
            super_dict[k] = []
        if v not in super_dict.get(k):
            super_dict[k].append(v)
Run Code Online (Sandbox Code Playgroud)

它可以更优雅/优化呈现吗?

注意 我在SO上发现了另一个问题,但它关于合并2个字典.

sen*_*rle 34

您可以直接迭代字典 - 无需使用range.setdefaultdict 的方法查找一个键,如果找到则返回该值.如果未找到,则返回默认值,并将该默认值分配给键.

super_dict = {}
for d in dicts:
    for k, v in d.iteritems():  # d.items() in Python 3+
        super_dict.setdefault(k, []).append(v)
Run Code Online (Sandbox Code Playgroud)

此外,您可以考虑使用defaultdict.这只是setdefault通过调用函数在未找到键时返回默认值来自动执行.

import collections
super_dict = collections.defaultdict(list)
for d in dicts:
    for k, v in d.iteritems():  # d.items() in Python 3+
        super_dict[k].append(v)
Run Code Online (Sandbox Code Playgroud)

此外,正如Sven Marnach精明地观察到的那样,您似乎不想在列表中重复值.在这种情况下,set获得你想要的东西:

import collections
super_dict = collections.defaultdict(set)
for d in dicts:
    for k, v in d.iteritems():  # d.items() in Python 3+
        super_dict[k].add(v)
Run Code Online (Sandbox Code Playgroud)


Ste*_*ski 25

from collections import defaultdict

dicts = [{'a':1, 'b':2, 'c':3},
         {'a':1, 'd':2, 'c':'foo'},
         {'e':57, 'c':3} ]

super_dict = defaultdict(set)  # uses set to avoid duplicates

for d in dicts:
    for k, v in d.items():  # use d.iteritems() in python 2
        super_dict[k].add(v)
Run Code Online (Sandbox Code Playgroud)

  • +1:这似乎正是问题所要求的(值中的唯一元素),以相对清晰且肯定有效的方式完成(字典经过一次,内置集只保留独特的元素快速)。 (2认同)

G_k*_*eep 21

您可以使用 dict 的这种行为。(有点优雅)

 a = {'a':1, 'b':2, 'c':3}
 b = {'d':1, 'e':2, 'f':3}
 c = {1:1, 2:2, 3:3}
 merge = {**a, **b, **c}
 print(merge) # {'a': 1, 'b': 2, 'c': 3, 'd': 1, 'e': 2, 'f': 3, 1: 1, 2: 2, 3: 3}
Run Code Online (Sandbox Code Playgroud)

你很高兴去:)

  • 就我而言,每个字典中的键都是唯一的,这正是我想要的。谢谢! (5认同)
  • 但是如何为未知数量的词典制作通用的呢? (3认同)
  • 您的解决方案替换键的值,而不是将它们组合在列表中。这是您的解决方案的结果:`{'a': 1, 'b': 2, 'c': 3, 'd': 2, 'e': 57}` (2认同)

Sve*_*ach 12

合并所有dicts的键,并为每个键组合值列表:

super_dict = {}
for k in set(k for d in dicts for k in d):
    super_dict[k] = [d[k] for d in dicts if k in d]
Run Code Online (Sandbox Code Playgroud)

该表达式set(k for d in dicts for k in d)构建了所有字典的所有唯一键的集合.对于这些唯一键中的每一个,我们使用列表[d[k] for d in dicts if k in d]推导来为此键的所有dicts构建值列表.

由于您似乎只是每个键的唯一值,因此您可能希望使用集合:

super_dict = {}
for k in set(k for d in dicts for k in d):
    super_dict[k] = set(d[k] for d in dicts if k in d)
Run Code Online (Sandbox Code Playgroud)


pbr*_*ach 6

似乎大多数使用推导式的答案都不是那么易读。万一在上面的答案混乱中迷失了,这可能会有所帮助(尽管非常晚......)。只需遍历每个字典的项目并将它们放在一个单独的项目中。

super_dict = {key:val for d in dicts for key,val in d.items()}
Run Code Online (Sandbox Code Playgroud)

  • OP 希望保留两个“c”值:“{'c':[3,'foo']}”。 (2认同)

小智 5

当键的值在列表中时:

from collections import defaultdict

    dicts = [{'a':[1], 'b':[2], 'c':[3]},
             {'a':[11], 'd':[2], 'c':['foo']},
             {'e':[57], 'c':[3], "a": [1]} ]

super_dict = defaultdict(list)  # uses set to avoid duplicates

for d in dicts:
    for k, v in d.items():  # use d.iteritems() in python 2
        super_dict[k] = list(set(super_dict[k] + v))

combined_dict = {}

for elem in super_dict.keys():
    combined_dict[elem] = super_dict[elem]

combined_dict
## output: {'a': [1, 11], 'b': [2], 'c': [3, 'foo'], 'd': [2], 'e': [57]}
Run Code Online (Sandbox Code Playgroud)