如何在python中合并并正确更新字典(其中value是列表)?

时间:2017-07-22 00:03:02

标签: python dictionary merge inner-join

假设我有两个值,其中值是列表(或者集合也很好,因为内容是唯一的)。例如:

dic1 = {'math': ['algebra', 'trigonometry', 'geometry']}
dic2 = {'math': ['calculus'], 'science': ['physics']}
dic2.update(dic1)

我想要的输出是这样的:

{'math': ['algebra', 'trigonometry', 'geometry', 'calculus'], 'science': ['physics']}

但我得到了:

{'math': ['algebra', 'trigonometry', 'geometry'], 'science': ['physics']}

基本上我想在合并两个dicts时合并内容(我不想覆盖而是保留两者)。有一个简单的方法吗?注意:在我给出的这个例子中,只有两个字典。虽然我还没有编写代码,但我最终还是想循环几个字典并在循环中进行合并/更新这个过程,这在建议方法时可能会有所帮助。

6 个答案:

答案 0 :(得分:2)

这可以用一个简单的单行表示:

>>> {k: dic1.get(k, []) + dic2.get(k, []) for k in (set(dic1) | set(dic2))}
{'science': ['physics'], 'math': ['algebra', 'trigonometry', 'geometry', 'calculus']}

这结合了三种技术:

Python的核心工具包通常为基本的基本数据操作问题提供优雅的解决方案。我经常对这些工具结合在一起感到惊讶。

这有助于: - )

答案 1 :(得分:1)

如果要合并多个列表序列,请避免重复:

def updateDict(dict1, dict2):
   for key in dict1:
      if key in dict2:
         prev_values = set(dict1[key]) # create set to retain only unique values in list
         prev_values.update(dict2[key])
         dict1[key] = list(prev_values)

答案 2 :(得分:0)

dict1 = {'math': ['algebra', 'trigonometry', 'geometry']}
dict2 = {'math': ['calclus'], 'science': ['physics']}
for key, value in dict1.items():
    dict2.setdefault(key, []).extend(value)

>>> print(dict2)
{'science': ['physics'], 'math': ['calclus', 'algebra', 'trigonometry', 'geometry']}

如果您想要保留两个字典值,请执行此操作

from copy import deepcopy

dict1 = {'math': ['algebra', 'trigonometry', 'geometry']}
dict2 = {'math': ['calclus'], 'science': ['physics'], 'lol':['lol1']}
dict3 = deepcopy(dict2)
for key, value in dict1.items():
    dict3.setdefault(key, []).extend(value)

>>>print(dict2)
{'science': ['physics'], 'math': ['calclus']}
>>>print(dict3)
{'science': ['physics'], 'math': ['calclus', 'algebra', 'trigonometry', 'geometry']}

答案 3 :(得分:0)

如果dic1不包含dic2中没有的键,那么这里的词典理解就会有效:

dic3 = {k: v + dic1.get(k, list()) for k, v in dic2.items()}

此外,为了确保将dic1中的任何缺失密钥添加到dict,您可以在此之后添加for循环。

for k, v in dic1.items():
    if k not in dic3:
        dic3.update({k: v})

答案 4 :(得分:0)

不知道一种直截了当的方式,但这应该有效:

def combine_dicts(dict1,dict2):
    dict = {}
    for key1,list1 in dict1.items():
        for key2,list2 in dict2.items():
           if key1 == key2:
               dict[key1] = list1.extend(list2)
    return dict

答案 5 :(得分:0)

您可以创建自己的字典类以获得所需的行为。我不确定什么是最好的方式,但这是一种可能性:

import collections

class ListDict(collections.UserDict):
    def update(self, other):
        if isinstance(other, collections.Mapping):
            for key, value in other.items():
                self.data.setdefault(key, []).extend(value)
        else:
            raise NotImplementedError()

dic1 = ListDict({'math': ['algebra', 'trigonometry', 'geometry']})
dic2 = ListDict({'math': ['calculus'], 'science': ['physics']})
dic2.update(dic1)
print(dic2)

输出:

{'math': ['calculus', 'algebra', 'trigonometry', 'geometry'], 'science': ['physics']}

请注意,这只是实现所需行为的开始。根据您的用途,您可能希望添加更多功能。例如,只实现了the ways of calling update中的一个。

为了防止生成的集合中出现重复值,您可能希望改为使用集合:

import collections

class SetDict(collections.UserDict):
    def update(self, other):
        if isinstance(other, collections.Mapping):
            for key, value in other.items():
                self.data[key] = self.data.get(key, set()).union(value)
        else:
            raise NotImplementedError()

dic3 = SetDict({'math': ['algebra', 'trigonometry']})  # may contain lists ...
dic4 = SetDict({'math': {'algebra', 'geometry'}})  # ... or sets
dic4.update(dic3)
print(dic4)

输出:

{'math': {'algebra', 'geometry', 'trigonometry'}}