合并两个字典并在Python中保留重复键的值

Net*_*iev 7 python merge dictionary

我们假设我有两个词典:

dic1 =  { "first":1, "second":4, "third":8} 
dic2 =  { "first":9, "second":5, "fourth":3}
Run Code Online (Sandbox Code Playgroud)

有没有直接的方法来获得如下所示的东西?

dic3 =  { "first":[1,9], "second":[4,5], "third":[8], "fourth":[3]}
Run Code Online (Sandbox Code Playgroud)

我使用列表存储值,但元组也很好.

Ale*_*der 8

您可以使用a defaultdict来保存列表,然后只需将值附加到它们.这种方法很容易扩展到任意数量的字典.

from collections import defaultdict

dd = defaultdict(list)

dics = [dic1, dic2]
for dic in dics:
    for key, val in dic.iteritems():  # .items() in Python 3.
        dd[key].append(val)

>>> dict(dd)
{'first': [1, 9], 'fourth': [3], 'second': [4, 5], 'third': [8]}
Run Code Online (Sandbox Code Playgroud)

具有单个值的所有键仍保留在列表中,这可能是最好的方法.但是,您可以将长度为1的任何内容更改为实际值,例如

for key, val in dd.iteritems():  # .items() in Python 3.
    if len(val) == 1
        dd[key] = val[0]
Run Code Online (Sandbox Code Playgroud)

  • 即使密钥中没有重复值,此实现也会使得到的`defaultdict`中的所有值都为`list`类型.如果首选行为是将单个值保留为该值的类型,那么我们应该在添加之前检查是否存在密钥,并且只有在该密钥已经存在时才转换为列表. (2认同)

ggo*_*len 6

这是一个天真的解决方案; 将其中一个字典复制到结果中,并迭代其他字典的键和值,并根据需要将数组添加到结果中.由于只有两个字典,因此合并数组不会超过2个字段; 无需检查类型.

dic1 = {"first": 1, "second": 4, "third": 8} 
dic2 = {"first": 9, "second": 5, "fourth": 3}
dic3 = dict(dic2)

for k, v in dic1.items():
    dic3[k] = [dic3[k], v] if k in dic3 else v

print(dic3)
Run Code Online (Sandbox Code Playgroud)

输出:

{'first': [9, 1], 'second': [5, 4], 'fourth': 3, 'third': 8}
Run Code Online (Sandbox Code Playgroud)

试一试.

如果您希望将单个值作为列表,则可以使用:

dic3 = {k: [v] for k, v in dic2.items()}

for k, v in dic1.items():
    dic3[k] = dic3[k] + [v] if k in dic3 else [v]
Run Code Online (Sandbox Code Playgroud)


PMe*_*nde 2

一般来说,我认为将不同键的值转换为不同的对象类型是不好的做法。我会简单地做类似的事情:

def merge_values(val1, val2):
    if val1 is None:
        return [val2]
    elif val2 is None:
        return [val1]
    else:
        return [val1, val2]
dict3 = {
    key: merge_values(dic1.get(key), dic2.get(key))
    for key in set(dic1).union(dic2)
}
Run Code Online (Sandbox Code Playgroud)