4

I am running into issues iterating through, and modifying, a dictionary...

Say I have a dictionary:

dict1 = {'A' : 'first', 'B' : 'second', 'C' : 'third', 'D' : 'fourth'}

I want to iterate through dict1, using the data within to build up a second dictionary. Once finished with each entry in dict1, I delete it.

In pseudocode:

dict2 = {}

for an entry in dict1:
    if key is A or B:
        dict2[key] = dict1[key]   # copy the dictionary entry
    if key is C:
        do this...
    otherwise:
        do something else...
    del dict1[key]

I know that altering the length of an iterable in a loop causes problems and the above may not be simple to achieve.

The answer to this question to this question seems to indicate that I can use the keys() function as it returns a dynamic object. I've thus tried:

for k in dict1.keys():
    if k == A or k == B:
        dict2[k] = dict1[k]
    elif k == C:
        dothis()
    else:
        dosomethingelse()
    del dict1[k]

But, this simply gives:

'RuntimeError: dictionary changed size during iteration'

after the first deletion. I have also tried using iter(dict1.keys()) but got the same error.

I'm thus a little confused and could do with some advice. Thanks

Community
  • 1
  • 1
user2696225
  • 359
  • 2
  • 7
  • 17
  • It appears that dict1 will always be empty when the loop finishes. So could you problem be solved by simply overwriting dict1 when you have completed your loop? – Jonas Apr 19 '17 at 22:12
  • http://stackoverflow.com/questions/12753351/removing-one-or-multiple-keys-from-a-dictionary http://stackoverflow.com/questions/8995611/removing-multiple-keys-from-a-dictionary-safely – Kenny Ostrom Apr 19 '17 at 22:19
  • iterate over `list(dict1.keys())` But why must you delete the keys one-by-one? Just `dict1.clear()` after the loop. – juanpa.arrivillaga Apr 19 '17 at 23:03

2 Answers2

5

Just use the .keys() method to create an independent list of keys.

Here is a working version of your code for Python 2.7:

>>> dict1 = {'A' : 'first', 'B' : 'second', 'C' : 'third', 'D' : 'fourth'}
>>> dict2 = {}
>>> for key in dict1.keys():     # this makes a separate list of keys
        if key in ('A', 'B'):
            dict2[key] = dict1[key]
        elif key == 'C':
            print 'Do this!'
        else:
            print 'Do something else'
        del dict1[key]

Do this!
Do something else
>>> dict1
{}
>>> dict2
{'A': 'first', 'B': 'second'}   

For Python 3, add list() around the .keys() and use the print-function:

>>> dict1 = {'A' : 'first', 'B' : 'second', 'C' : 'third', 'D' : 'fourth'}
>>> dict2 = {}
>>> for key in list(dict1.keys()):     # this makes a separate list of keys
        if key in ('A', 'B'):
            dict2[key] = dict1[key]
        elif key == 'C':
            print('Do this!')
        else:
            print('Do something else')
        del dict1[key]

Do this!
Do something else
>>> dict1
{}
>>> dict2
{'A': 'first', 'B': 'second'}   
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
3

why not simply dict1.clear()? notice that on your loop you delete each element per iteration?

one simplified (and naive) solution I can think about is

delkeys=[]
dict2 = {}

for an entry in dict1:
  if key is A or B:
    dict2[key] = dict1[key]         # copy the dictionary entry
  if key is C:
    do this...
  elif:
    do something else...
  delkeys.append(key)

for x in delkeys:
   del dict1[x]
LiorA
  • 441
  • 3
  • 13