如何在循环中删除Counter对象中的条目而不引发RuntimeError?
from collections import *
ignore = ['the','a','if','in','it','of','or']
ArtofWarCounter = Counter(ArtofWarLIST)
for word in ArtofWarCounter:
if word in ignore:
del ArtofWarCounter[word]
ArtofWarCounter是一个计数器对象,里面包含了《孙子兵法》中的所有单词。我想把ignore
里列出的单词从ArtofWarCounter中删除。
错误追踪信息:
File "<pyshell#10>", line 1, in <module>
for word in ArtofWarCounter:
RuntimeError: dictionary changed size during iteration
4 个回答
1
请查看下面的问题,了解为什么你现在的方法不起作用:
在遍历列表时删除项目
简单来说,当你在遍历一个集合(比如列表或字典)的时候,不应该在这个集合里添加或删除任何东西。collections.Counter
是 dict
的一个子类,下面是文档中关于 dict.iteritems()
的警告:
在使用
iteritems()
的时候,如果你在字典中添加或删除条目,可能会引发RuntimeError
,或者无法遍历所有条目。
19
不要对字典里的所有单词进行循环查找,这样效率很低。字典在查找时表现得更好。
你可以遍历 ignore
列表,删除那些已经存在的条目:
ignore = ['the','a','if','in','it','of','or']
for word in ignore:
if word in ArtofWarCounter:
del ArtofWarCounter[word]
20
为了尽量减少代码的修改,可以使用 list
,这样你正在遍历的对象就和 Counter
分开了。
ignore = ['the','a','if','in','it','of','or']
ArtofWarCounter = Counter(ArtofWarLIST)
for word in list(ArtofWarCounter):
if word in ignore:
del ArtofWarCounter[word]
在 Python2 中,你可以用 ArtofWarCounter.keys()
来代替 list(ArtofWarCounter)
,但是既然写出更能适应未来变化的代码这么简单,为什么不这样做呢?
更好的做法是直接不去计算那些你想忽略的项目。
ignore = {'the','a','if','in','it','of','or'}
ArtofWarCounter = Counter(x for x in ArtofWarLIST if x not in ignore)
注意,我把 ignore
变成了一个 set
,这样测试 x not in ignore
就会高效得多。