[英]Sum the nested dictionary values in python
I have a dictionary like this, 我有这样的字典,
data={11L: [{'a': 2, 'b': 1},{'a': 2, 'b': 3}],
22L: [{'a': 3, 'b': 2},{'a': 2, 'b': 5},{'a': 4, 'b': 2},{'a': 1, 'b': 5}, {'a': 1, 'b': 0}],
33L: [{'a': 1, 'b': 2},{'a': 3, 'b': 5},{'a': 5, 'b': 2},{'a': 1, 'b': 3}, {'a': 1, 'b': 6},{'a':2,'b':0}],
44L: [{'a': 4, 'b': 2},{'a': 4, 'b': 5},{'a': 3, 'b': 1},{'a': 3, 'b': 3}, {'a': 2, 'b': 3},{'a':1,'b':2},{'a': 1, 'b': 0}]}
Here i ll get rid of the outer keys, and give new key values 1, 2 , 3 so on, i want to get the result as shown below, 在这里我将摆脱外键,并给出新的键值1,2,3等,我想得到如下所示的结果,
result={1:{'a':10,'b':7},2:{'a':11,'b':18},3:{'a':12,'b':5},4:{'a':5,'b':11},5:{'a':3,'b':9},6:{'a':3,'b':2},7:{'a':1,'b':0}}
I tried some thing like this, but i dint get the required result, 我试过这样的事情,但我得到了所需的结果,
d = defaultdict(int)
for dct in data.values():
for k,v in dct.items():
d[k] += v
print dict(d)
I want the keys of result dictionary to be dynamic, like in the above data dictionary we have 44 which has highest with 7 key value pairs, hence we have the result dictionary with 7 keys and so on 我希望结果字典的键是动态的,就像在上面的数据字典中我们有44个最高的7个键值对,因此我们有7个键的结果字典等等
You want to use a list here, and you want to perhaps use Counter()
objects to make the summing that much easier: 你想在这里使用一个列表,你想要使用
Counter()
对象来使得求和更容易:
from collections import Counter
from itertools import izip_longest
for dcts in data.values():
for i, dct in enumerate(dcts):
if i >= len(result):
result.append(Counter(dct))
else:
result[i].update(dct)
Result: 结果:
>>> result
[Counter({'a': 10, 'b': 7}), Counter({'b': 18, 'a': 11}), Counter({'a': 12, 'b': 5}), Counter({'b': 11, 'a': 5}), Counter({'b': 9, 'a': 4}), Counter({'a': 3, 'b': 2}), Counter({'a': 1, 'b': 0})]
Counter()
objects are subclasses of dict
, so they otherwise behave as dictionaries. Counter()
对象是dict
子类,因此它们表现为字典。 If you have to have dict
values afterwards, add the following line: 如果之后必须有
dict
值,请添加以下行:
result = [dict(r) for r in result]
Taking inspiration from Eric, you can transform the above into a one-liner: 从Eric那里获取灵感,您可以将上述内容转化为单行:
from collections import Counter
from itertools import izip_longest
result = [sum(map(Counter, col), Counter())
for col in izip_longest(*data.values(), fillvalue={})]
This version differs slightly from the loop above in that keys that are 0 are dropped from the counter when summing. 这个版本与上面的循环略有不同,因为在求和时从计数器中删除了0的键。 If you want to keep
'b': 0
in the last counter, use: 如果你想在最后一个计数器中保持
'b': 0
,请使用:
[reduce(lambda c, d: c.update(d) or c, col, Counter())
for col in izip_longest(*data.values(), fillvalue={})]
This uses .update()
again. 这再次使用
.update()
。
izip_longest
allows you to transpose the rows: izip_longest
允许您转置行:
from itertools import izip_longest
print [
{
'a': sum(cell['a'] for cell in column),
'b': sum(cell['b'] for cell in column)
}
for column in izip_longest(*data.values(), fillvalue={'a': 0, 'b': 0})
]
[{'a': 10, 'b': 7}, {'a': 11, 'b': 18}, {'a': 12, 'b': 5}, {'a': 5, 'b': 11}, {'a': 4, 'b': 9}, {'a': 3, 'b': 2}, {'a': 1, 'b': 0}]
Or combining that with counters: 或者将它与计数器结合:
print [
sum(Counter(cell) for cell in column, Counter())
for column in izip_longest(*data.values(), fillvalue={})
]
[Counter({'a': 10, 'b': 7}), Counter({'b': 18, 'a': 11}), Counter({'a': 12, 'b': 5}), Counter({'b': 11, 'a': 5}), Counter({'b': 9, 'a': 4}), Counter({'a': 3, 'b': 2}), Counter({'a': 1, 'b': 0})]
First find the length of the longest list among all the values (which are lists): 首先在所有值(列表)中找到最长列表的长度:
max_length = 0
for key in data.keys():
if max_length < len(data[key]):
max_length = len(data[key])
In your case, max_length = 7
. 在您的情况下,
max_length = 7
。 Now iterate as follows: 现在迭代如下:
result = {}
for i in range(max_length):
result[i+1] = {'a': 0, 'b': 0} # i + 1 since the result starts with key = 1
for key in data.keys():
if i < len(data[key]):
result[i+1]['a'] += data[key][i]['a']
result[i+1]['b'] += data[key][i]['b']
You should get: 你应该得到:
print result
{1: {'a': 10, 'b': 7}, 2: {'a': 11, 'b': 18}, 3: {'a': 12, 'b': 5}, 4: {'a': 5, 'b': 11}, 5: {'a': 4, 'b': 9}, 6: {'a': 3, 'b': 2}, 7: {'a': 1, 'b': 0}}
Edit: @user2286041 If you'd like the result
dict to be reduced to 编辑: @ user2286041如果您希望
result
dict减少到
reduced_result = {'a': [10, 11,12,5,4,3,1], 'b': [7, 18,5,11,9,2,0]}
then you can try the following code: 然后你可以尝试以下代码:
reduced_result = {}
inner_keys = ['a', 'b']
for inner_key in inner_keys:
temp = []
for outer_key in result:
temp.append(result[outer_key][inner_key])
reduced_result[inner_key] = temp
I'm not sure though how to get the inner_keys
in a more general way, aside from explicitly specifying them. 我不确定如何以更一般的方式获取
inner_keys
,除了明确指定它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.