例如,我有两个字典:
Dict A: {'a': 1, 'b': 2, 'c': 3}
Dict B: {'b': 3, 'c': 4, 'd': 5}
我需要一种python的方式来“组合”两个字典,这样的结果是:
{'a': 1, 'b': 5, 'c': 7, 'd': 5}
也就是说:如果一个键在两个字典中都出现,则将它们的值相加,如果它只在一个字典中出现,则保留其值。
例如,我有两个字典:
Dict A: {'a': 1, 'b': 2, 'c': 3}
Dict B: {'b': 3, 'c': 4, 'd': 5}
我需要一种python的方式来“组合”两个字典,这样的结果是:
{'a': 1, 'b': 5, 'c': 7, 'd': 5}
也就是说:如果一个键在两个字典中都出现,则将它们的值相加,如果它只在一个字典中出现,则保留其值。
当前回答
要获得更通用和可扩展的方法,请检查mergedict。它使用singledispatch,并可以根据类型合并值。
例子:
from mergedict import MergeDict
class SumDict(MergeDict):
@MergeDict.dispatch(int)
def merge_int(this, other):
return this + other
d2 = SumDict({'a': 1, 'b': 'one'})
d2.merge({'a':2, 'b': 'two'})
assert d2 == {'a': 3, 'b': 'two'}
其他回答
import itertools
import collections
dictA = {'a':1, 'b':2, 'c':3}
dictB = {'b':3, 'c':4, 'd':5}
new_dict = collections.defaultdict(int)
# use dict.items() instead of dict.iteritems() for Python3
for k, v in itertools.chain(dictA.iteritems(), dictB.iteritems()):
new_dict[k] += v
print dict(new_dict)
# OUTPUT
{'a': 1, 'c': 7, 'b': 5, 'd': 5}
OR
你也可以像@Martijn上面提到的那样使用Counter。
人物介绍: 有(可能)最好的解决方案。但你必须知道并记住它,有时你必须希望你的Python版本不是太旧或其他问题。
还有一些最“俗气”的解决方案。它们伟大而简短,但有时却很难理解、阅读和记忆。
不过,还有另一种选择,那就是尝试重新发明轮子。 -为什么要重新发明轮子? -一般来说,这是一个很好的学习方法(有时只是因为现有的工具不能完全按照你想要的方式来做),如果你不知道或不记得解决你的问题的完美工具,这是最简单的方法。
因此,我建议从collections模块重新发明Counter类的轮子(至少部分地):
class MyDict(dict):
def __add__(self, oth):
r = self.copy()
try:
for key, val in oth.items():
if key in r:
r[key] += val # You can custom it here
else:
r[key] = val
except AttributeError: # In case oth isn't a dict
return NotImplemented # The convention when a case isn't handled
return r
a = MyDict({'a':1, 'b':2, 'c':3})
b = MyDict({'b':3, 'c':4, 'd':5})
print(a+b) # Output {'a':1, 'b': 5, 'c': 7, 'd': 5}
可能还有其他的方法来实现它,而且已经有工具可以做到这一点,但是把事情的基本原理可视化总是很好的。
def merge_with(f, xs, ys):
xs = a_copy_of(xs) # dict(xs), maybe generalizable?
for (y, v) in ys.iteritems():
xs[y] = v if y not in xs else f(xs[x], v)
merge_with((lambda x, y: x + y), A, B)
你可以很容易地概括如下:
def merge_dicts(f, *dicts):
result = {}
for d in dicts:
for (k, v) in d.iteritems():
result[k] = v if k not in result else f(result[k], v)
然后它可以取任意数量的字典。
来自python 3.5:合并和求和
Thanks to @tokeinizer_fsj that told me in a comment that I didn't get completely the meaning of the question (I thought that add meant just adding keys that eventually where different in the two dictinaries and, instead, i meant that the common key values should be summed). So I added that loop before the merging, so that the second dictionary contains the sum of the common keys. The last dictionary will be the one whose values will last in the new dictionary that is the result of the merging of the two, so I thing the problem is solved. The solution is valid from python 3.5 and following versions.
a = {
"a": 1,
"b": 2,
"c": 3
}
b = {
"a": 2,
"b": 3,
"d": 5
}
# Python 3.5
for key in b:
if key in a:
b[key] = b[key] + a[key]
c = {**a, **b}
print(c)
>>> c
{'a': 3, 'b': 5, 'c': 3, 'd': 5}
可重用代码
a = {'a': 1, 'b': 2, 'c': 3}
b = {'b': 3, 'c': 4, 'd': 5}
def mergsum(a, b):
for k in b:
if k in a:
b[k] = b[k] + a[k]
c = {**a, **b}
return c
print(mergsum(a, b))
下面是另一个使用字典推导式结合dict()行为的选项:
dict3 = dict(dict1, **{ k: v + dict1.get(k, 0) for k, v in dict2.items() })
# {'a': 4, 'b': 2, 'c': 7, 'g': 1}
从https://docs.python.org/3/library/stdtypes.html dict类型:
https://docs.python.org/3/library/stdtypes.html#dict
也
如果给出了关键字参数,则关键字参数及其值将被添加到由位置参数创建的字典中。
词典理解
**{ k: v + dict1.get(v, 0), v in dict2.items() }
处理将dict1[1]添加到v.中。这里不需要显式if,因为dict1的默认值。Get可以设置为0。