Python 如何将嵌套字典转换为平面字典并使用重复键求和值?

Python 如何将嵌套字典转换为平面字典并使用重复键求和值?,python,dictionary,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

这是我的字典:

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
然而,正如你所看到的,它不是很优雅。一定有更好的办法!(雷蒙德·赫廷格:D)

我还可以做听写理解,显然每个键只保留一个条目:

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}
(显然没有意义,只是为了说明这一点)


正在寻找最干净的方法来执行此操作

您可以使用
集合。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}
{'a': 5, 'b': 10, 'c': 13, 'd': 10}
Counter({'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}
{'a': 5, 'b': 10, 'c': 13, 'd': 10}
Counter({'a': 5, 'b': 10, 'c': 13, 'd': 10})

您可以使用集合。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}
{'a': 5, 'b': 10, 'c': 13, 'd': 10}
Counter({'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}
{'a': 5, 'b': 10, 'c': 13, 'd': 10}
Counter({'a': 5, 'b': 10, 'c': 13, 'd': 10})

使用集合的另一种方法。计数器:

from collections import Counter

sum(map(Counter, d.values()), Counter())
输出:

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

使用集合的另一种方法。计数器:

from collections import Counter

sum(map(Counter, d.values()), Counter())
输出:

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

很不错的。。怀疑这是否可以改善,但我不能再接受5分钟,所以我们会看到:非常好。。怀疑这是否可以改善,但我不能再接受5分钟,所以我们将看到:D