0

I want to delete some items in a dictionary in a for loop, then I follow the codes from this How to delete items from a dictionary while iterating over it?

Looping over .keys:

b = {'a':1, 'b' : 2}
for k in b.keys():
    if b[k] == 1:
        del b[k]

Results in:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
b
{'b': 2}

Similarly, looping over .items():

b = {'a':1, 'b' : 2}
for k, v in b.items():
    if v == 1:
        del b[k]

Traceback (most recent call last):
  File "<input>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
b
{'b': 2}

After the loop, it returns the correct result, but RuntimeError is also raised, how can I fix it?

Community
  • 1
  • 1
user5802211
  • 197
  • 1
  • 9

2 Answers2

3

You alter d with del d[k] so iterating over it's .keys or .values makes no difference, you alter the underlying iterator and so it complains.

You could either make a list of the .keys, with list(b), or .items, with list(b.items()), essentially copying them to a new iterator that doesn't relate to the dictionary you're altering:

# list(b) would suffice instead of .keys
for k in list(b.keys()):
    if b[k] == 1:
        del b[k]

or, use a dict comprehension:

d = {k:b[k] for k in b if b[k] != 1}

to filter out unwanted elements.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
2

You can't remove elements in a dict while iterating over it.

The best way would be to use a dict comprehension:

b = {'a':1, 'b' : 2}
b = {k: v for k, v in b.items() if v != 1}

You could also make a copy of your dict while iterating over it:

b = {'a':1, 'b' : 2}
for k, v in dict(b).items():
    if v == 1:
        del b[k]

Here, you are iterating over a copy of b while modifying the original b, this is why it works: you are never removing elements from the copy.

Pierre Barre
  • 2,174
  • 1
  • 11
  • 23