关于python:检查给定的键是否已经存在于字典中并递增它

Check if a given key already exists in a dictionary and increment it

给定一个字典,我如何才能确定该字典中的给定键是否已设置为非无值?

也就是说,我想这样做:

1
2
3
4
5
6
my_dict = {}

if (my_dict[key] != None):
  my_dict[key] = 1
else:
  my_dict[key] += 1

也就是说,如果已经有一个值,我想增加这个值,否则设置为1。


您正在查找collections.defaultdict(可用于python 2.5+)。这个

1
2
3
4
from collections import defaultdict

my_dict = defaultdict(int)
my_dict[key] += 1

会做你想做的。

对于常规的python dicts,如果给定的键没有值,那么在访问dict时就不会得到None——会引发KeyError。因此,如果您想使用常规的dict,而不是您的代码,您将使用

1
2
3
4
if key in my_dict:
    my_dict[key] += 1
else:
    my_dict[key] = 1


我更喜欢用一行代码来完成这项工作。

1
2
3
my_dict = {}

my_dict[some_key] = my_dict.get(some_key, 0) + 1

字典有一个函数get,它接受两个参数——您想要的键,如果不存在的话还有一个默认值。我更喜欢这个方法而不是默认dict,因为您只想处理键不在这一行代码中的情况,而不是在任何地方。


我个人喜欢使用setdefault()

1
2
3
4
my_dict = {}

my_dict.setdefault(some_key, 0)
my_dict[some_key] += 1

为此,您需要使用key in dict习惯用法。

1
2
3
4
if key in my_dict and not (my_dict[key] is None):
  # do something
else:
  # do something else

但是,您可能应该考虑使用defaultdict(如df建议的那样)。


要回答"如何确定该dict中的给定索引是否已设置为非无值"的问题,我希望这样做:

1
2
3
4
try:
  nonNone = my_dict[key] is not None
except KeyError:
  nonNone = False

这符合已经被调用的EAFP概念(先请求原谅,后请求许可)。它还避免了字典中的重复键查找,就像在key in my_dict and my_dict[key] is not None中一样,如果查找成本很高,有什么有趣的。

对于您提出的实际问题,例如,如果存在int,则递增它,或者将其设置为默认值,否则,我还建议

1
my_dict[key] = my_dict.get(key, default) + 1

就像安德鲁·威尔金森的回答一样。

如果要在字典中存储可修改对象,则还有第三种解决方案。这方面的一个常见示例是多映射,在多映射中存储键的元素列表。在这种情况下,您可以使用:

1
my_dict.setdefault(key, []).append(item)

如果字典中不存在键的值,setdefault方法会将其设置为setdefault的第二个参数。它的行为就像标准的my-dict[键],返回键的值(可能是新设置的值)。


同意CGoldberg。我是怎么做到的:

1
2
3
4
try:
    dict[key] += 1
except KeyError:
    dict[key] = 1

所以要么像上面所说的那样做,要么像其他人建议的那样使用默认的dict。不要使用if语句。那不是Python。


正如您从许多答案中看到的,有几个解决方案。还没有提到lbyl的一个实例(在跳跃前查看),has_key()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
my_dict = {}

def add (key):
    if my_dict.has_key(key):
        my_dict[key] += 1
    else:
        my_dict[key] = 1

if __name__ == '__main__':
    add("foo")
    add("bar")
    add("foo")
    print my_dict


您尝试这样做的方式称为lbyl(在跳跃之前查看),因为您在尝试增加值之前检查条件。

另一种方法称为EAFP(先请求原谅,后请求许可)。在这种情况下,您只需尝试该操作(增加值)。如果失败,则捕获异常并将值设置为1。这是一个稍微多一些的Python式的方法来做它(IMO)。

http://mail.python.org/pipermail/python-list/2003-may/205182.html


这不是直接回答问题,但在我看来,您可能需要collections.counter的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from collections import Counter

to_count = ["foo","foo","bar","baz","foo","bar"]

count = Counter(to_count)

print(count)

print("acts just like the desired dictionary:")
print("bar occurs {} times".format(count["bar"]))

print("any item that does not occur in the list is set to 0:")
print("dog occurs {} times".format(count["dog"]))

print("can iterate over items from most frequent to least:")
for item, times in count.most_common():
    print("{} occurs {} times".format(item, times))

这将导致输出

1
2
3
4
5
6
7
8
9
Counter({'foo': 3, 'bar': 2, 'baz': 1})
acts just like the desired dictionary:
bar occurs 2 times
any item that does not occur in the list is set to 0:
dog occurs 0 times
can iterate over items from most frequent to least:
foo occurs 3 times
bar occurs 2 times
baz occurs 1 times


有点晚了,但这应该管用。

1
2
my_dict = {}
my_dict[key] = my_dict[key] + 1 if key in my_dict else 1


这是我最近为解决这个问题而提出的一条建议。它基于setdefault dictionary方法:

1
2
my_dict = {}
my_dict[key] = my_dict.setdefault(key, 0) + 1


我在找它,没有在网上找到它,然后用try/error试试运气,找到了它。

1
2
3
4
5
6
my_dict = {}

if my_dict.__contains__(some_key):
  my_dict[some_key] += 1
else:
  my_dict[some_key] = 1