user3474154
user3474154

Reputation:

Adding and combining values with dictionary comprehensions?

Let's say I have a list:

a_list = [["Bob", 2], ["Bill", 1], ["Bob", 2]]

I want to add these to a dictionary and combining the values to the corresponding key. So, in this case, I want a dictionary that looks like this:

{"Bob" : 4, "Bill" : 1}

How can I do that with dictionary comprehensions?

This is what I have:

d1 = {group[0]: int(group[1]) for group in a_list}

Upvotes: 2

Views: 1149

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121366

To do what you want with a dictionary comprehension, you'd need an external extra dictionary to track values per name so far:

memory = {}
{name: memory[name] for name, count in a_list if not memory.__setitem__(name, count + memory.setdefault(name, 0))}

but this produces two dictionaries with the sums:

>>> a_list = [["Bob", 2], ["Bill", 1], ["Bob", 2]]
>>> memory = {}
>>> {name: memory[name] for name, count in a_list if not memory.__setitem__(name, count + memory.setdefault(name, 0))}
{'Bob': 4, 'Bill': 1}
>>> memory
{'Bob': 4, 'Bill': 1}

That's because without the memory dictionary you cannot access the running sum per name.

At that point you may as well just use a dictionary and a regular loop:

result = {}
for name, count in a_list:
    result[name] = result.get(name, 0) + count

or a collections.defaultdict() object:

from collections import defaultdict

result = defaultdict(int)
for name, count in a_list:
    result[name] += count

or even a collections.Counter() object, giving you additional multi-set functionality for later:

from collections import Counter

result = Counter()
for name, count in a_list:
    result[name] += count

The other, less efficient option is to sort your a_list first and then use itertools.groupby)():

from itertools import groupby
from operator import itemgetter

key = itemgetter(0)  # sort by name
{name: sum(v[1] for v in group)
 for name, group in groupby(sorted(a_list, key=key), key)}

This is a O(NlogN) approach vs. the straightforward O(N) approach of a loop without a sort.

Upvotes: 3

Related Questions