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,
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
You want to use a list here, and you want to perhaps use Counter() objects to make the summing that much easier:
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. If you have to have dict values afterwards, add the following line:
result = [dict(r) for r in result]
Taking inspiration from Eric, you can transform the above into a one-liner:
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. If you want to keep 'b': 0 in the last counter, use:
[reduce(lambda c, d: c.update(d) or c, col, Counter())
for col in izip_longest(*data.values(), fillvalue={})]
This uses .update() again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With