Reputation:
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
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