在Python中,计算两个嵌套字典中相似键的值的总和

8
我有一个像这样的嵌套字典:

data = {
    "2010":{
            'A':2,
            'B':3,
            'C':5,
            'D':-18,
        },
    "2011":{
            'A':1,
            'B':2,
            'C':3,
            'D':1,
        },
    "2012":{
            'A':1,
            'B':2,
            'C':4,
            'D':2
        }
    }

在我的情况下,我需要根据每年相似的键来汇总所有值,从2010年到2012年。因此,我期望的结果应该是这样的:

data = {'A':4,'B':7, 'C':12, 'D':-15}
2个回答

4
您可以使用collections.Counter()(仅适用于正值!):
In [17]: from collections import Counter
In [18]: sum((Counter(d) for d in data.values()), Counter())
Out[18]: Counter({'C': 12, 'B': 7, 'A': 4, 'D': 3})

请注意,根据Python文档,Counter的设计仅适用于具有正值的用例: 引用: 多重集方法仅设计用于具有正值的用例。输入可能为负数或零,但只创建具有正值的输出。没有类型限制,但值类型需要支持加法、减法和比较。'elements()'方法要求整数计数。它忽略零和负计数。
因此,如果您想获得全面的结果,您可以手动求和。使用collections.defaultdict()是解决此问题的好方法:
In [28]: from collections import defaultdict

In [29]: d = defaultdict(int)

In [30]: for sub in data.values():
   ....:     for i, j in sub.items():
   ....:         d[i] += j
   ....:         

In [31]: d
Out[31]: defaultdict(<class 'int'>, {'D': -15, 'A': 4, 'C': 12, 'B': 7})

In [20] 发生了什么? - Elmex80s
1
@RahulKP 有趣的观点!应该是15。让我再检查一下。 - Mazdak
3
这看起来很好而且紧凑,但是是不正确的。Counter类定义了__add__(..)方法,只有在结果为正数时才会进行更新。详见:https://github.com/python/cpython/blob/3.6/Lib/collections/__init__.py#L705 - UltraInstinct
更新后仍有4个反对票! :-) 我的回答还有什么问题吗? - Mazdak

2

请试试这个:

reduce(lambda x, y: dict((k, v + y[k]) for k, v in x.iteritems()), data.values())

结果

{'A': 4, 'B': 7, 'C': 12, 'D': -15}

1
这非常不专业且难以维护,我认为stackoverflow不应该成为“谁编写最佳代码”的平台。即使是对Python有很多了解的人,在理解这个之前也必须仔细查看。少量的代码并不等于更好的代码。 - Markus Meskanen

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