简体   繁体   中英

Python: summing up list of dictionaries with different keys and same values

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?

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}

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})

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}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM