0

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}
AiKw
  • 29
  • 4
  • 1
    I guess it's *possible*, but perhaps somewhat unwieldy. Have you tried something…? – deceze Nov 16 '21 at 10:54
  • 1
    Why do you want to write it in one line? You can put any number of statements into the same line by separating them with `;` but you shouldn't do it since it hurts the readability of your code. You can also do it within a single statement, but that will hurt readability too. – a_guest Nov 16 '21 at 10:54
  • Related: [merge-and-sum-of-two-dictionaries](https://stackoverflow.com/questions/10461531/merge-and-sum-of-two-dictionaries) – Patrick Artner Nov 16 '21 at 11:03

3 Answers3

3

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)
user2390182
  • 72,016
  • 6
  • 67
  • 89
1

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)
deceze
  • 510,633
  • 85
  • 743
  • 889
0

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 --+
a_guest
  • 34,165
  • 12
  • 64
  • 118