例如,我有两个 dicts:

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

我需要合并两个 dicts 的 pythonic 方法,这样的结果是︰

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

也就是说︰ 如果项同时出现在两个 dicts,添加它们的值,如果它出现在只有一个的 dict,保留其值。

2012-06-13 09:17:28
问题评论:

记录︰ 如何有效地合并两个以上的 dicts 信息,请参阅我在stackoverflow.com/a/11290471/399317的答案 :-)

这已被错误地标记为重复。合并,使用最新的 wins (类似于dict.update()); 处理冲突提出的其他问题这个问题假设的整数值,并要求增加。这可能看起来像小的区别,但这也意味着,任何在其他问题上最常见的解决方案都将应用到这台,因此将其标记为重复项的彼此是相当具有误导性。

回答:

使用collections.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的子类,这样仍可以执行一切与其像通常那样做这类型,如循环访问其键和值。

什么这里是要合并的多个计数器像这样吗?sum(counters)不起作用,遗憾的是。

@Jan-PhilipGehrcke︰ 为sum()提供的起始值,与sum(counters, Counter()).

谢谢。但是,此方法是受中间对象创建求和字符串原样,对吗?

@Jan-PhilipGehrcke︰ 您另一个选项是使用循环和+= = 要就地求和。res = counters[0],然后for c in counters[1:]: res += c.

我喜欢这种方法 !如果有人喜欢保持接近处理词典的内容,还可以使用update()而不是 + +=:for c in counters[1:]: res.update(c).

适用于非数字值以及一个更具一般性解决方案︰

a = {'a': 'foo', 'b':'bar', 'c': 'baz'}
b = {'a': 'spam', 'c':'ham', 'x': 'blah'}

r = dict(a.items() + b.items() +
    [(k, a[k] + b[k]) for k in set(b) & set(a)])

或更多泛型︰

def combine_dicts(a, b, op=operator.add):
    return dict(a.items() + b.items() +
        [(k, op(a[k], b[k])) for k in set(b) & set(a)])

例如︰

>>> a = {'a': 2, 'b':3, 'c':4}
>>> b = {'a': 5, 'c':6, 'x':7}

>>> import operator
>>> print combine_dicts(a, b, operator.mul)
{'a': 10, 'x': 7, 'c': 24, 'b': 3}

您也可以使用for k in b.viewkeys() & a.viewkeys(),当使用 python 2.7,并跳过创建集。

>>> 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}

set(A)就是set(A.keys()),以便您可以删除对.keys()的调用.

...,在 python 中 2.x,执行set(A)稍快比做set(A.keys()) ,因为您避免创建额外的序列生成的keys() (使用set(A)只是原因A set()返回迭代器对象调用).

不使用for x in set(itertools.chain(A, B))是更符合逻辑吗?作为对 dict 使用组是键都已经是唯一有点意义吗?我知道只是另一种方法来获取一组密钥但我发现它令人困惑,比使用itertools.chain (这意味着您知道什么itertools.chain的作用)

这应该是顶级的答案。

简介︰有的 (可能) 最佳解决方案。但您必须知道并记住它,有时您必须到 Python 版本不太旧的希望或可能是任何问题。

然后有一些最类似二次修改的解决方案。他们是好和短但有时很难理解、 阅读和记忆。

没有,不过,这是为尝试从头的替代方法。-为什么后尘吗?-通常因为它是学习非常好方法 (和有时只是因为现有工具不完全您想和 (或) 方式想要) 和最简单的方法,如果您不知道或不记得您的问题的理想工具。

因此,我建议要从头Counter类的collections模块 (部分至少):

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}

那里或许其他人实现的方法和已有的工具来执行,但是总是很好以可视化方式事情基本上会工作。

对于我们这些仍在 2.6 好也

myDict = {}
for k in itertools.chain(A.keys(), B.keys()):
    myDict[k] = A.get(k, 0)+B.get(k, 0)
请输入您的翻译

Is there any pythonic way to combine two dicts (adding values for keys that appear in both)?

确认取消