Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I remove entries within a Counter object with a loop without invoking a 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 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
like image 252
Louis93 Avatar asked Aug 22 '11 22:08

Louis93


People also ask

How do you remove an element from a countertop?

We can use del to delete an element from the counter object.

What does counter () do in Python?

Counter is a subclass of dict that's specially designed for counting hashable objects in Python. It's a dictionary that stores objects as keys and counts as values. To count with Counter , you typically provide a sequence or iterable of hashable objects as an argument to the class's constructor.

How do you access elements in a counter Python?

Accessing Elements in Python Counter To get the list of elements in the counter we can use the elements() method. It returns an iterator object for the values in the Counter.


2 Answers

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]
like image 67
Jochen Ritzel Avatar answered Sep 17 '22 06:09

Jochen Ritzel


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

like image 44
John La Rooy Avatar answered Sep 21 '22 06:09

John La Rooy