2012-05-28 2 views
1

Я использую SetDefault для подсчета экземпляров, как это (это версия stripdown):Использование SetDefault, но не желая передать обратно на карту/Dict

user_to_count_map = {} 
for username in list_of_usernames: 
    x = user_to_count_map.setdefault(username, 0) 
    x += 1 
    user_to_count_map[username] = x + 1 
for username in sorted(usernmae_to_count_map): 
    print username, user_to_count_map[username] 

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

ответ

1

Вы могли бы сделать прилавок список с одним элементом, эффективно делая его изменчивым:

user_to_count_map = {} 
for username in list_of_usernames: 
    x = user_to_count_map.setdefault(username, [0]) 
    x[0] += 1 
for username, counter in sorted(user_to_count_map.items()): 
    print username, counter[0] 

Я не уверен, что это делает ваш код более читаемым, так как явное лучше, чем неявное.

Или, если использовать Python 2.7 или более поздней версии (или использовать convenient backport), вы можете использовать Counter object:

from collections import Counter 
user_to_count_map = Counter() 
for username in list_of_usernames: 
    user_to_count_map[username] += 1 
for username, counter in sorted(user_to_count_map.items()): 
    print username, counter[0]   

Обратите внимание, что при использовании Counter у вас есть словарь, который автоматически дает вам значение по умолчанию 0. В противном случае он действует как словарь с целыми значениями, поэтому вы можете увеличивать и уменьшать эти значения любым способом (включая добавление более 1).

То же самое можно использовать с defaultdict, также в модуле коллекций, но обратите внимание, что класс Counter предлагает функциональность. defaultdict присутствует в python 2.5 и выше; Пример:

from collections import defaultdict 
user_to_count_map = defaultdict(lambda: 0) 
for username in list_of_usernames: 
    user_to_count_map[username] += 1 

В качестве альтернативы, вы можете просто отказаться от SetDefault вообще, как вы всегда назначая обратно к отображению в любом случае:

user_to_count_map = {} 
for username in list_of_usernames: 
    x = user_to_count_map.get(username, 0) 
    x += 1 
    user_to_count_map[x] = x 
for username, counter in sorted(user_to_count_map.items()): 
    print username, counter[0] 
+0

Ошибка синтаксиса присутствовала в OP, исправлена. :-) –

+0

@pieters спасибо за исправление типа, cut & Paste сложно с 4 дополнительными пробелами, поэтому я набрал. Я думаю, что я буду использовать синтаксис списка некоторое время. Ницца заключается в том, что 'x + = 1' дает TypeError x - список! – Gerard

+0

@ user1421439: SO делает код вставки простым; просто вставьте, убедитесь, что выбран весь код и нажмите кнопку ('{}') на панели инструментов или используйте комбинацию клавиш CTRL-K. –

5

Для подсчета элементов, следует использовать Counter:

import collections 
user_counts = collections.Counter(list_of_usernames) 
print(user_counts.most_common()) 

В качестве альтернативы, get метод в dict делает то же самое, как setdefault, но без побочного эффекта запоминания значения в Словаре:

user_to_count_map = {} 
for username in list_of_usernames: 
    user_to_count_map[username] = user_to_count_map.get(username, 0) + 1 
+0

ooh, nice one. Счетчики идеально подходят для его использования. –

+0

Думаю, я упростил пример. Поскольку фактическое значение, которое добавляется для каждого элемента зависимости, изменяется в цикле for и вычислении, зависящем от исходного значения на карте при входе и других вещах. С помощью счетчика мне нужно будет сделать еще один счетчик для увеличения, например. 72 значения 'user_counts + = Счетчик (имя пользователя, 72)' – Gerard

+0

@ user1421439: Счетчик может сделать это за вас, см. Мой обновленный ответ. –

0

Если вам не нравится SetDefault и всегда начинаются с 0 Вы можете do:

from collections import defaultdict 

user_to_count_map = defaultdict(lambda: [0]) 
for username in list_of_usernames: 
    # no set_default 
    user_to_count_map[username][0] += value 

for username, counter in sorted(user_to_count_map.items()): 
    print username, counter[0] 
+0

Зачем возвращать список по умолчанию в этом случае? Вы можете просто использовать lambda: 0 и не индексировать. –

Смежные вопросы