2016-03-27 2 views
3

Предоставлена ​​установка так:Python ДИКТ понимание суммируя от объектов

class Foo(): 
    state = 'x' 
    amount = 1 


a = Foo() 
b = Foo() 
c = Foo() 
c.state = 'y' 
foos = [a, b, c] 

Я хочу, чтобы получить Dict, который имеет ключи = object.state, значение = sum(object.amounts of objects with that state). В этом случае:

{'x': 2, 'y': 1} 

Я хочу сделать это автоматически, поэтому мне не нужно заранее знать разные возможные состояния.

Конечно, я мог бы перебирать в какой-то скучной манере, как это:

my_dict = {} 
for foo in foos: 
    try: 
     my_dict[foo.state] += foo.value 
    except (KeyError, TypeError): 
     my_dict[foo.state] = foo.value 

Но это немного многословен, и мне интересно, если есть лучше способ сделать это, возможно, с Dict постижений или что-то, но мои усилия до сих пор были напрасны.

+0

Где находится 'foo.type'? –

+0

К сожалению, исправлено, было из старой версии. –

ответ

3

Как насчет 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}) 
+1

@ Kasramvd .. мой плохой .. Я работал с 'itertools' в то же время по другому вопросу ..: P –

+0

Для полноты можно выполнить' Counter (f.state для f в foos для x в диапазоне (f.amount)) ', но я не чувствую, что это достаточно хорошо, чтобы получить отдельный ответ. – arekolek

2

В этом случае понимание словаря не является самым оптимизированным подходом. Вместо этого вы можете использовать collections.defaultdict() как следующее:

>>> from collections import defaultdict 
>>> d = defaultdict(int) 
>>> 
>>> for obj in foos: 
...  d[obj.state] += obj.amount 
... 
>>> d 
defaultdict(<type 'int'>, {'y': 1, 'x': 2}) 
1

Вы можете использовать defaultdict.

from collections import defaultdict 
my_dict = defaultdict(lambda: 0) 
for foo in foos: 
    my_dict[foo.type] += foo.value 

Вы также можете использовать setdefault.

my_dict = {} 
for foo in foos: 
    my_dict.setdefault(foo.type, 0) 
    my_dict[foo.type] += foo.value 
Смежные вопросы