Update dictionary keys in a loop in python

Viewed 5220

I want to update the keys of my dictionary c with its new keys k_new. Even though I am referring different stack overflow questions like this it does not get updated. Please tell me where I make it wrong.

from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
c = {'apples': 3, 'biscuits and tea': 3, 'oranges and onions': 4}
for k in c:
    splits=k.split()
    k_new= " ".join(lemmatizer.lemmatize(w.lower()) for w in splits)
    c[k_new] = c.pop(k)
print(c)

PS: I also used:

c[k_new] = c[k]
del c[k]

Then I get RuntimeError: dictionary changed size during iteration

Please help me

2 Answers

You update the dictionary while you iterate over it:

from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
c = {'apples': 3, 'biscuits and tea': 3, 'oranges and onions': 4}
for k in c:  # iterate over c
    splits=k.split()
    k_new= " ".join(lemmatizer.lemmatize(w.lower()) for w in splits)
    c[k_new] = c.pop(k)  # update (two times) c
print(c)

updating a collection while you iterate over it is usually a very bad idea. Most data structures are not designed to handle this.

You can however construct a new dictionary:

from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
c = {'apples': 3, 'biscuits and tea': 3, 'oranges and onions': 4}
c_new = {}
for k in c:
    splits=k.split()
    k_new= " ".join(lemmatizer.lemmatize(w.lower()) for w in splits)
    c_new[k_new] = c[k]
print(c_new)

We can make this more elegant by using dictionary comprehension:

{" ".join(lemmatizer.lemmatize(w.lower()) for w in k.split()): v
 for k,v in c.items()}

this one-liner constructs a new dictionary where we iterate over key-value pairs k,v of c, and add a key " ".join(lemmatizer.lemmatize(w.lower()) for w in k.split()) that we associate with the value v.

Iterating over dictionary while it is changing might have weired effects since you are using a real-time reference to the keys. Just make a list out of the key view and it will work:

for k in list(c):
    ...
Related