I have a list of dictionaries like this.
fruit = [{"apple": 10, "pear": 20, "banana": 30, "strawberry": 50},
{"apple": 12, "pear": 5, "banana": 20, "strawberry": 5},
{"apple": 15, "pear": 26, "banana": 32, "strawberry": 8}]
Can I write an reduce function in one line(with lambda argument) to get a new dictionary with the same keys. The value to each key of the new dictionary is the sum of all the values to the corresponding key. The expected output should be a dictionary as follows:
{'apple': 37.0, 'pear': 51.0, 'banana': 82.0, 'strawberry': 63.0}
CodePudding user response:
Util-heavy approach:
from operator import add
from collections import Counter
from functools import reduce
reduce(add, map(Counter, fruit))
# Counter({'banana': 82, 'strawberry': 63, 'pear': 51, 'apple': 37})
Or maybe more instructive for the beginner, writing an add
for two dicts:
def add(d1, d2):
return {k: d1.get(k, 0) d2.get(k, 0) for k in d1.keys() | d2.keys()}
reduce(add, fruit)
CodePudding user response:
A dict-comprehension can do the work of merging two dicts like this:
>>> from functools import reduce
>>> fruit = [{"apple": 10, "pear": 20, "banana": 30, "strawberry": 50},
... {"apple": 12, "pear": 5, "banana": 20, "strawberry": 5},
... {"apple": 15, "pear": 26, "banana": 32, "strawberry": 8}]
>>> reduce(lambda a, b: {k: a[k] v for k, v in b.items()}, fruit)
{'apple': 37, 'pear': 51, 'banana': 82, 'strawberry': 63}
This does require that all dicts have the same keys, otherwise some will be dropped. The more complete version is this, which does get pretty unwieldy as a reduce-lambda though:
reduce(lambda a, b: {k: a.get(k, 0) b.get(k, 0) for k in a.keys() | b.keys()}, fruit)
CodePudding user response:
The following approach uses a dict comprehension and no imports. I don't recommend to use it however:
{k: sum(f.get(k,0) for f in fruit) for k in {k for f in fruit for k in f}}
# | |
# -- set of all fruit keys --