例如,我有两个字典:

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}

也就是说:如果一个键在两个字典中都出现,则将它们的值相加,如果它只在一个字典中出现,则保留其值。


当前回答

是什么:

def dict_merge_and_sum( d1, d2 ):
    ret = d1
    ret.update({ k:v + d2[k] for k,v in d1.items() if k in d2 })
    ret.update({ k:v for k,v in d2.items() if k not in d1 })
    return ret

A = {'a': 1, 'b': 2, 'c': 3}
B = {'b': 3, 'c': 4, 'd': 5}

print( dict_merge_and_sum( A, B ) )

输出:

{'d': 5, 'a': 1, 'c': 7, 'b': 5}

其他回答

myDict = {}
for k in itertools.chain(A.keys(), B.keys()):
    myDict[k] = A.get(k, 0)+B.get(k, 0)

明确地对Counter()求和是在这种情况下最python化的方法,但前提是它的结果为正值。下面是一个例子,正如你所看到的,在B字典中对c的值求负后,结果中没有c。

In [1]: from collections import Counter

In [2]: A = Counter({'a':1, 'b':2, 'c':3})

In [3]: B = Counter({'b':3, 'c':-4, 'd':5})

In [4]: A + B
Out[4]: Counter({'d': 5, 'b': 5, 'a': 1})

这是因为计数器主要用于使用正整数来表示运行计数(负计数是没有意义的)。但是为了帮助这些用例,python记录了最小范围和类型限制如下:

The Counter class itself is a dictionary subclass with no restrictions on its keys and values. The values are intended to be numbers representing counts, but you could store anything in the value field. The most_common() method requires only that the values be orderable. For in-place operations such as c[key] += 1, the value type need only support addition and subtraction. So fractions, floats, and decimals would work and negative values are supported. The same is also true for update() and subtract() which allow negative and zero values for both inputs and outputs. The multiset methods are designed only for use cases with positive values. The inputs may be negative or zero, but only outputs with positive values are created. There are no type restrictions, but the value type needs to support addition, subtraction, and comparison. The elements() method requires integer counts. It ignores zero and negative counts.

为了在Counter求和之后解决这个问题你可以使用Counter。更新以获得所需的输出。它的工作方式类似于dict.update(),但添加计数而不是替换它们。

In [24]: A.update(B)

In [25]: A
Out[25]: Counter({'d': 5, 'b': 5, 'a': 1, 'c': -1})
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。

一种解决方法是使用字典理解。

C = { k: A.get(k,0) + B.get(k,0) for k in list(B.keys()) + list(A.keys()) }
>>> A = {'a':1, 'b':2, 'c':3}
>>> B = {'b':3, 'c':4, 'd':5}
>>> c = {x: A.get(x, 0) + B.get(x, 0) for x in set(A).union(B)}
>>> print(c)

{'a': 1, 'c': 7, 'b': 5, 'd': 5}