Python:将两个内容相似的字典合并

3

我正在寻找一种Pythonic的方式(尽可能少的代码)来合并两个字典的内容:

basket1 = {"ham":2,"eggs":3}
basket2 = {"eggs":4,"spam":1}

我希望获得第三个篮子,它将是另外两个篮子的“总和”,篮子3应该是:
basket3 --> {"ham":2,"eggs":7,"spam":1}

如果可能的话,可以使用 set 来完成此操作。

3个回答

10

我会使用一个Counter,它是一种带有一些不错特性的defaultdict

>>> from collections import Counter
>>> basket1 = {"ham":2,"eggs":3}
>>> basket2 = {"eggs":4,"spam":1}
>>> basket_sum = Counter(basket1) + Counter(basket2)
>>> basket_sum
Counter({'eggs': 7, 'ham': 2, 'spam': 1})

如果需要,您可以将其转换回纯 dict:

>>> dict(basket_sum)
{'eggs': 7, 'ham': 2, 'spam': 1}

+1,你比我先了。此外,常规链接指向参考文档http://docs.python.org/3/library/collections.html#collections.Counter。 - poke
有趣的计数器使用 - inspectorG4dget
@Speccy:不是直接的。但是如果你编写一个帮助函数将Food实例列表转换为字典,例如def basket_to_dict(basket): return {f.name: f.quantity for f in basket},那么类似于[Food(n,q) for n,q in (Counter(basket_to_dict(b1)) + Counter(basket_to_dict(b2))).iteritems()]这样的代码就可以工作了。(Python >= 2.7.) - DSM

4

由于您正在尝试计算值,请使用collections.Counter

basket3 = collections.Counter(basket1)
basket3.update(basket2)

或者:

basket3 = collections.Counter(basket1) + collections.Counter(basket2)

@Speccy:请查看新版本。 - abarnert
+1 是为了展示 update 方法。知道 update 对于 Counter 类型的字典有不同的行为是很有用的。 - Akavall
谢谢,我会选择得票最高的答案,它基本上与您的相同。 - Speccy
@Speccy:对于未来的搜索者来说,它可能比我的更好,因为它显示了更多的细节,所以接受它是正确的选择。 - abarnert
@abarnert,如果我有一个Food类的实例列表(具有名称和数量属性),并且我想要删除重复项并更新列表中每个唯一Food类实例的总数量,那么这样的方法是否可行? - Speccy
@Speccy:你的意思是countFood的成员吗?不,如果是这样,你需要做一些不同的事情。你可以始终创建两个Counter({food: quantity for food in foods})对象,将它们相加,然后在事后转换回列表。但此时,手动创建两个set可能更简单,或者向Food添加一个update方法,或者... - abarnert

2
In [2]: basket1 = {"ham":2,"eggs":3}

In [3]: basket2 = {"eggs":4,"spam":1}

In [4]: baskets = [basket1, basket2]

In [5]: answer = collections.defaultdict(int)

In [6]: for basket in baskets:
   ...:     for item in basket:
   ...:         answer[item] += basket[item]
   ...:         

In [7]: answer
Out[7]: defaultdict(<type 'int'>, {'eggs': 7, 'ham': 2, 'spam': 1})

In [8]: dict(answer)
Out[8]: {'eggs': 7, 'ham': 2, 'spam': 1}

需要的是各个字典中重复键的值的总和,而不是包含特定键的字典数量。 - Kyle Strand
我认为可以通过将 answer[item] += 1 更改为 answer[item] += basket[item] 来修复这个问题。 - DSM
这就是我想做的。已修复! - inspectorG4dget
等等,你怎么能得到数字9的“eggs”? - DSM
@DSM:那是上一次试验中泄露的“答案”。请查看更新。 - inspectorG4dget

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接