Mat
Mat

Reputation: 515

How to change a dictionary while iterating over its keys while iterating over a list

  1. I have a list l.
  2. I have a dictionary d.

I want to iterate over l. For any list-item, I want to iterate over the d.keys.

If some condition is met, I would like to 'update' my dictionary.

I have naively tried to nest two for-loops and put in an if-statement -- One cannot change the length of the object one is iterating over.

d = {'this': '1', 'is': '2', 'a': '3', 'list': '4'}

l = ['A', 'B', 'C', 'D', 'E']

for word in l:
    for key in d.keys():
        if len(key) < 2:#some condition
            d.pop(key)
        else:
            print(word, key)

This is the output I get:

A this
A is
Traceback (most recent call last):
  File "untitled3.py", line 6, in <module>
    for key in d.keys():
RuntimeError: dictionary changed size during iteration

Upvotes: 3

Views: 4543

Answers (2)

Joshua Nixon
Joshua Nixon

Reputation: 1427

Instead of looping over d you could loop over a copy.

d = {'this': '1', 'is': '2', 'a': '3', 'list': '4'}

l = ['A', 'B', 'C', 'D', 'E']

for word in l:
    for key in d.copy().keys(): # Notice the change
        if len(key) < 2:#some condition
            d.pop(key)
        else:
            print(word, key)

Upvotes: 4

jpp
jpp

Reputation: 164623

You should not change the size of a dictionary while iterating over a view of that dictionary. You can, instead, construct a new dictionary and then print whatever you like. For example:

d = {'this': '1', 'is': '2', 'a': '3', 'list': '4'}
L = ['A', 'B', 'C', 'D', 'E']

d_new = {k: v for k, v in d.items() if len(k) >= 2}

for word in L:
    for key in d_new:
        print(word, key)

As described in the docs:

The objects returned by dict.keys(), dict.values() and dict.items() are view objects. They provide a dynamic view on the dictionary’s entries, which means that when the dictionary changes, the view reflects these changes.... Iterating views while adding or deleting entries in the dictionary may raise a RuntimeError or fail to iterate over all entries.

Upvotes: 2

Related Questions