Как удалить записи в объекте Counter с помощью цикла, не вызывая RuntimeError? - PullRequest
10 голосов
/ 23 августа 2011
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 - объект Counter, содержащий все слова из Art of War. Я пытаюсь удалить слова из ignore из ArtofWarCounter.

Traceback:

  File "<pyshell#10>", line 1, in <module>
    for word in ArtofWarCounter:
RuntimeError: dictionary changed size during iteration

Ответы [ 4 ]

15 голосов
/ 23 августа 2011

Не зацикливайтесь на всех словах диктата, чтобы найти запись, они лучше подходят при поиске.

Вы перебираете список ignore и удаляете существующие записи:

ignore = ['the','a','if','in','it','of','or']
for word in ignore:
    if word in ArtofWarCounter:
        del ArtofWarCounter[word]
12 голосов
/ 23 августа 2011

Для минимальных изменений кода используйте 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 намного более эффективным

1 голос
/ 23 августа 2011

См. Следующий вопрос, почему ваш текущий метод не работает:
Удаление элементов из списка при итерации

По сути, вы не должны добавлять или удалять элементы из коллекции, покаВы зацикливаетесь на этом.collections.Counter является подклассом dict, см. Следующее предупреждение в документации для dict.iteritems():

Использование iteritems() при добавлении или удалении записей в словареможет вызвать RuntimeError или не выполнить итерацию по всем записям.

0 голосов
/ 23 августа 2011

Используйте счетчик, пройдитесь по петле назад (от последнего к первому), удалите при необходимости.Цикл до нуля.

...