Reputation: 6616
Given a setup like this:
class Foo():
state = 'x'
amount = 1
a = Foo()
b = Foo()
c = Foo()
c.state = 'y'
foos = [a, b, c]
I want to get a dict that has keys = object.state
, values = sum(object.amounts of objects with that state)
. In this case:
{'x': 2, 'y': 1}
I want to do this automatically, so I don't need to know the different possible states in advance.
For sure I could iterate through in some boring manner like this:
my_dict = {}
for foo in foos:
try:
my_dict[foo.state] += foo.value
except (KeyError, TypeError):
my_dict[foo.state] = foo.value
But that is a bit verbose, and I'm wondering if there's a nicer way to do it, maybe with dict comprehensions or something, but my efforts so far have been in vain.
Upvotes: 3
Views: 523
Reputation: 107347
Dictionary comprehension is not the most optimized approach in this case. Instead you can use collections.defaultdict()
like following :
>>> from collections import defaultdict
>>> d = defaultdict(int)
>>>
>>> for obj in foos:
... d[obj.state] += obj.amount
...
>>> d
defaultdict(<type 'int'>, {'y': 1, 'x': 2})
Upvotes: 2
Reputation: 10951
How about Counter
:
>>> from collections import Counter
>>>
>>> foos = [a,b,c]
>>>
>>> c = Counter()
>>> for x in foos:
c[x.state] += x.amount
>>> c
Counter({'x': 2, 'y': 1})
Upvotes: 3
Reputation: 414
You could use defaultdict.
from collections import defaultdict
my_dict = defaultdict(lambda: 0)
for foo in foos:
my_dict[foo.type] += foo.value
You could also use setdefault.
my_dict = {}
for foo in foos:
my_dict.setdefault(foo.type, 0)
my_dict[foo.type] += foo.value
Upvotes: 1