例如,我有两个字典:

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}

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


当前回答

上述解决方案非常适合具有少量计数器的场景。如果你有一个很大的列表,像这样的就更好了:

from collections import Counter

A = Counter({'a':1, 'b':2, 'c':3})
B = Counter({'b':3, 'c':4, 'd':5}) 
C = Counter({'a': 5, 'e':3})
list_of_counts = [A, B, C]

total = sum(list_of_counts, Counter())

print(total)
# Counter({'c': 7, 'a': 6, 'b': 5, 'd': 5, 'e': 3})

上述解决方案本质上是通过以下方法对计数器求和:

total = Counter()
for count in list_of_counts:
    total += count
print(total)
# Counter({'c': 7, 'a': 6, 'b': 5, 'd': 5, 'e': 3})

这个做的是同样的事情,但我认为它总是有助于看到它在下面有效地做了什么。

其他回答

另外,请注意a.update(b)比a + b快2倍

from collections import Counter
a = Counter({'menu': 20, 'good': 15, 'happy': 10, 'bar': 5})
b = Counter({'menu': 1, 'good': 1, 'bar': 3})

%timeit a + b;
## 100000 loops, best of 3: 8.62 µs per loop
## The slowest run took 4.04 times longer than the fastest. This could mean that an intermediate result is being cached.

%timeit a.update(b)
## 100000 loops, best of 3: 4.51 µs per loop
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。

使用集合。计数器:

>>> from collections import Counter
>>> A = Counter({'a':1, 'b':2, 'c':3})
>>> B = Counter({'b':3, 'c':4, 'd':5})
>>> A + B
Counter({'c': 7, 'b': 5, 'd': 5, 'a': 1})

计数器基本上是dict的一个子类,因此您仍然可以使用它们执行通常使用该类型执行的所有其他操作,例如遍历它们的键和值。

将三个字典a,b,c合并到一行中,没有任何其他模块或库

如果我们有三个字典

a = {"a":9}
b = {"b":7}
c = {'b': 2, 'd': 90}

将所有内容合并为一行,并使用返回一个dict对象

c = dict(a.items() + b.items() + c.items())

返回

{'a': 9, 'b': 2, 'd': 90}

这是一个很一般的解。你可以处理任意数量的dict +键,只在一些dict +容易使用任何聚合函数你想要:

def aggregate_dicts(dicts, operation=sum):
    """Aggregate a sequence of dictionaries using `operation`."""
    all_keys = set().union(*[el.keys() for el in dicts])
    return {k: operation([dic.get(k, None) for dic in dicts]) for k in all_keys}

例子:

dicts_same_keys = [{'x': 0, 'y': 1}, {'x': 1, 'y': 2}, {'x': 2, 'y': 3}]
aggregate_dicts(dicts_same_keys, operation=sum)
#{'x': 3, 'y': 6}

不相同的键和泛型聚合示例:

dicts_diff_keys = [{'x': 0, 'y': 1}, {'x': 1, 'y': 2}, {'x': 2, 'y': 3, 'c': 4}]

def mean_no_none(l):
    l_no_none = [el for el in l if el is not None]
    return sum(l_no_none) / len(l_no_none)

aggregate_dicts(dicts_diff_keys, operation=mean_no_none)
# {'x': 1.0, 'c': 4.0, 'y': 2.0}