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

时间:2018-09-28 21:32:57

标签: python dictionary merge

让我们假设我有两个字典:

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

是否有一种简单的方法来获取类似于以下内容的内容?

dic3 =  { "first":[1,9], "second":[4,5], "third":[8], "fourth":[3]}

我使用列表来存储值,但是元组也可以。

8 个答案:

答案 0 :(得分:6)

您可以使用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]}

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

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

答案 1 :(得分: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)

输出:

{'first': [9, 1], 'second': [5, 4], 'fourth': 3, 'third': 8}

Try it out

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

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]

答案 2 :(得分:3)

使用集合和字典理解

L = [d1, d2]
dups = set(d1.keys() & d2.keys())
d = {k: [L[0][k], L[1][k]] if k in dups else i[k] for i in L for k in i}
{'first': [1, 9], 'second': [4, 5], 'third': 8, 'fourth': 3}

答案 3 :(得分: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)
}

答案 4 :(得分:1)

给出:

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

您可以使用.setdefault

dic_new={}
for k,v in list(dic1.items())+list(dic2.items()):
    dic_new.setdefault(k, []).append(v)
else:
    dic_new={k:v if len(v)>1 else v[0] for k,v in dic_new.items()}  

>>> dic_new
{'first': [1, 9], 'second': [4, 5], 'third': 8, 'fourth': 3}

这将产生相关的输出。我认为将单个元素列表展平为不同的对象类型是不必要的复杂性。


进行编辑后,将产生所需的结果:

dic_new={}
for k,v in list(dic1.items())+list(dic2.items()):
    dic_new.setdefault(k, []).append(v)

>>> dic_new
{'first': [1, 9], 'second': [4, 5], 'third': [8], 'fourth': [3]}

答案 5 :(得分:1)

创建一个新字典dic,其中的键为dic1dic2,并为一个空列表赋值,然后遍历dic1dic2追加值dic

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

dic = {key:[] for key in list(dic1.keys()) + list(dic2.keys())}

for key in dic1.keys():
    dic[key].append(dic1[key])

for key in dic2.keys():
    dic[key].append(dic2[key])

答案 6 :(得分:0)

from copy import deepcopy


def _add_value_to_list(value, lis):
    if value:
        if isinstance(value, list):
            lis.extend(value)
        else:
            lis.append(value)
    else:
        pass


def _merge_value(value_a, value_b):
    merged_value = []
    _add_value_to_list(value_a, merged_value)
    _add_value_to_list(value_b, merged_value)
    return merged_value


def _recursion_merge_dict(new_dic, dic_a, dic_b):
    if not dic_a or not dic_b:
        return new_dic
    else:
        if isinstance(new_dic, dict):
            for k, v in new_dic.items():
                new_dic[k] = _recursion_merge_dict(v, dic_a.get(k, {}), dic_b.get(k, {}))
            return new_dic
        else:
            return _merge_value(dic_a, dic_b)


def merge_dicts(dic_a, dic_b):
    new_dic = deepcopy(dic_a)
    new_dic.update(dic_b)

    return _recursion_merge_dict(new_dic, dic_a, dic_b)

答案 7 :(得分:0)

列表字典的解决方案(改编自@dawg):

dic1 =  { "first":[1], "second":[4], "third":[8]} 
dic2 =  { "first":[9], "second":[5], "fourth":[3]}
dic_new={}
for k,v in list(dic1.items())+list(dic2.items()):
    dic_new.setdefault(k, []).extend(v)
>>> dic_new
{'first': [1, 9], 'second': [4, 5], 'third': [8], 'fourth': [3]}