问题
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 is a Counter object containing all the words from the Art of War. I'm trying to have words in ignore
deleted from the ArtofWarCounter.
Traceback:
File "<pyshell#10>", line 1, in <module>
for word in ArtofWarCounter:
RuntimeError: dictionary changed size during iteration
回答1:
For minimal code changes, use list
, so that the object you are iterating over is decoupled from the Counter
ignore = ['the','a','if','in','it','of','or']
ArtofWarCounter = Counter(ArtofWarLIST)
for word in list(ArtofWarCounter):
if word in ignore:
del ArtofWarCounter[word]
In Python2, you can use ArtofWarCounter.keys()
instead of list(ArtofWarCounter)
, but when it is so simple to write code that is futureproofed, why not do it?
It is a better idea to just not count the items you wish to ignore
ignore = {'the','a','if','in','it','of','or'}
ArtofWarCounter = Counter(x for x in ArtofWarLIST if x not in ignore)
note that I made ignore
into a set
which makes the test x not in ignore
much more efficient
回答2:
Don't loop over all words of a dict to find a entry, dicts are much better at lookups.
You loop over the ignore
list and remove the entries that exist:
ignore = ['the','a','if','in','it','of','or']
for word in ignore:
if word in ArtofWarCounter:
del ArtofWarCounter[word]
回答3:
See the following question for why your current method is not working:
Remove items from a list while iterating
Basically you should not add or remove items from a collection while you are looping over it. collections.Counter
is a subclass of dict
, see the following warning in the documentation for dict.iteritems():
Using
iteritems()
while adding or deleting entries in the dictionary may raise aRuntimeError
or fail to iterate over all entries.
回答4:
Use a counter, traverse the loop backwards (last to first), remove as needed. Loop until zero.
来源:https://stackoverflow.com/questions/7154312/how-do-i-remove-entries-within-a-counter-object-with-a-loop-without-invoking-a-r