如何将嵌套字典变成平面字典并使用重复键求和?

时间:2019-09-10 01:28:36

标签: python dictionary

这是我的字典:

d = {'dicta':{'a':1,'b':2,'c':3}, 'dictb':{'a':2,'b':3,'c':1}, 'dictc':{'a':2,'b':5,'c':9,'d':10}}

{'dicta': {'a': 1, 'b': 2, 'c': 3}, 'dictb': {'a': 2, 'b': 3, 'c': 1}, 'dictc': {'a': 2, 'b': 5, 'c': 9, 'd': 10}}

我想做的是将这些嵌套的dict合并为一个扁平的dict,并求和以得到以下值:

{'a': 5, 'b': 10, 'c': 13, 'd': 10}

我已经可以使用以下代码实现这一目标:

out = {}
for k,v in [[k2,d[k1][k2]] for k1 in d for k2 in d[k1]]:
    if k in out.keys():
        out[k] = out[k] + v
    else:
        out[k] = v

但是,正如您所见,它不是很优雅。肯定有更好的办法! (Raymond Hettinger:D)。

我还可以进行dict理解,显然每个键只保留一个条目:

out = {k2:d[k1][k2] for k1 in d for k2 in d[k1]}

输出:{'a': 2, 'b': 5, 'c': 9, 'd': 10}

或至少能给我我想要结合的一切的列表理解:

out = [{k2:d[k1][k2]} for k1 in d for k2 in d[k1]]

输出:[{'a': 1}, {'b': 2}, {'c': 3}, {'a': 2}, {'b': 3}, {'c': 1}, {'a': 2}, {'b': 5}, {'c': 9}]

感觉就像我正在接近...

是否有一种方法可以将我想要的方式以一种我从未意识到的优雅方式组合在一起?

类似这样的东西:out = {k2:d[k1][k2] for k1 in d for k2 in d[k1] with combined = True}(显然没有道理,只是为了说明这一点)

寻找最干净的方法

2 个答案:

答案 0 :(得分:3)

您可以使用collections.defaultdict

from collections import defaultdict
d = {'dicta':{'a':1,'b':2,'c':3}, 'dictb':{'a':2,'b':3,'c':1}, 'dictc':{'a':2,'b':5,'c':9,'d':10}}
_d = defaultdict(int)
for a in d.values():
  for c, j in a.items():
     _d[c] += j

print(dict(_d))

输出:

{'a': 5, 'b': 10, 'c': 13, 'd': 10}

使用itertools.groupby的更严格的解决方案:

from itertools import groupby
r = sorted([i for b in d.values() for i in b.items()], key=lambda x:x[0])
result = {a:sum(c for _, c in b) for a, b in groupby(r, key=lambda x:x[0])}

输出:

{'a': 5, 'b': 10, 'c': 13, 'd': 10}

答案 1 :(得分:1)

使用collections.Counter的另一种方法:

from collections import Counter

sum(map(Counter, d.values()), Counter())

输出:

Counter({'a': 5, 'b': 10, 'c': 13, 'd': 10})