使用setdefault,但不想重新分配回map / dict

时间:2012-05-28 10:09:46

标签: python setdefault

我使用setdefault计算这样的实例(这是条带版本):

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]

我不喜欢分配回地图,因为实际代码更复杂,多次计数增加。但我似乎确实需要这样做。有一个简单的方法吗?

3 个答案:

答案 0 :(得分:5)

要计算元素,您应该使用Counter

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

或者,dict的{​​{3}}方法与setdefault的方法相同,但没有将值存储在dict中的副作用:

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

答案 1 :(得分: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中使用,也可以在collections模块中使用,但请注意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]

答案 2 :(得分:0)

如果您不喜欢setdefault并始终以0开头,则可以执行以下操作:

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]