Qn: Nested dictionary cleanup

C

Colin Brown

My code fragment below:

for key1 in dict1.keys():
for key2 in dict1[key1]:
if dict1[key1][key2] == None:
del dict1[key1][key2]

gives the following error:
RuntimeError: dictionary changed size during iteration

Any suggestion on how to code this please.

Thanks
Colin Brown
PyNZ
 
S

Skip Montanaro

Colin> for key1 in dict1.keys():
Colin> for key2 in dict1[key1]:
Colin> if dict1[key1][key2] == None:
Colin> del dict1[key1][key2]

Should be

for key1 in dict1.keys():
for key2 in dict1[key1].keys():
if dict1[key1][key2] == None:
del dict1[key1][key2]

Note that the inner for loop explicitly calls .keys(). That creates an
explicit list. You loop over that instead of an iterator. Why did you
choose to call dict1.keys() but not dict1[key1].keys()?

Skip
 
E

Emile van Sebille

Colin Brown:
My code fragment below:

for key1 in dict1.keys():

here you realize an iterable list
for key2 in dict1[key1]:

here you step through an iterator. If you change this to
for key2 in dict1[key1].keys():

and assuming I've guessed appropriately, you might get what you're looking
for.
if dict1[key1][key2] == None:
del dict1[key1][key2]

Emile van Sebille
(e-mail address removed)
 
C

Colin Brown

OOPS!

Coding slip I'm afraid, sorry. I was thinking that the
code was failing because keys() were being evaluated
dynamically. I then tried to think how to queue the
deletes to be done after the loop but could not
figure out how to do this.

Colin
 
P

Peter Otten

Colin said:
My code fragment below:

for key1 in dict1.keys():
for key2 in dict1[key1]:
if dict1[key1][key2] == None:
del dict1[key1][key2]

gives the following error:
RuntimeError: dictionary changed size during iteration

Any suggestion on how to code this please.

Thanks
Colin Brown
PyNZ

In addition to Emile van Sebille's fix, the following tries to avoid
dictionary lookups:

# dict1 is not changed so we need not copy the values
for innerdict in dict1.itervalues():
# innerdict is changed so let's make a copy of the items
for key, value in innerdict.items():
if value is None:
del innerdict[key]


Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,169
Messages
2,570,919
Members
47,460
Latest member
eibafima

Latest Threads

Top