user8566323
user8566323

Reputation:

Update dictionary keys in a loop in python

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

Upvotes: 4

Views: 5767

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476544

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.

Upvotes: 3

Klaus D.
Klaus D.

Reputation: 14369

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):
    ...

Upvotes: 2

Related Questions