0

I have the following list of dictionaries with different keys and values. Every dictionary has only one key-value pair.

[{'a':1}, {'b':1}, {'a':1}, {'b':2}]

I need the following output preferably using list/dict comprehension

[{'a': 2, 'b': 3}]

I had a look on a similar question, but wasn't lucky to figure it out. Any suggestions please?

Joseph Wahba
  • 660
  • 3
  • 9
  • 25

3 Answers3

4

you could use collections.Counter:

from collections import Counter

lst = [{'a':1}, {'b':1}, {'a':1}, {'b':2}]

c = Counter()

for dct in lst: 
    c.update(dct)

print(c)
# Counter({'b': 3, 'a': 2})
hiro protagonist
  • 44,693
  • 14
  • 86
  • 111
3

There is an answer in the question you linked to that works as is:

dict1 = [{'a':1}, {'b':1}, {'a':1}, {'b':2}]

final = {}
for d in dict1:
    for k in d.keys():
        final[k] = final.get(k,0) + d[k]

print (final)

Yields:

{'a': 2, 'b': 3}
David Buck
  • 3,752
  • 35
  • 31
  • 35
2

This can be done in a single line without any imports using some clever reducing

To understand how this works, you have to understand how reduce works. Essentially, it allows you define an operation which takes two element from the list and reduces them down to a single element. It then applies this operation recursively to your list until the list has been reduced to a single element. Here is the one-line version:

dict1 = [{'a':1}, {'b':1}, {'a':1}, {'b':2}]

print(reduce(lambda a, b: {k: a.setdefault(k, 0) + b.setdefault(k, 0) for k in set(a.keys()).union(b.keys())}, dict1))

In this case, the operation is defined as:

lambda a, b: 
        {k: a.setdefault(k, 0) + b.setdefault(k, 0) for k in (set(a.keys()).union(b.keys()))}

Which can also be expressed as:

# a and b are two elements from the list. In this case they are dictionaries
def combine_dicts(a, b):
    output = {}
    for k in set(a.keys()).union(b.keys()): # the union of the keys in a and b
        output[k] = a.setdefault(k, 0) + b.setdefault(k, 0)
        # dict.setdefault returns the provided value if the key doesn't exist
    return output

When this operation is applied to your list with reduce, you get the desired output:

>>> {'b': 3, 'a': 2}