Trying to change dictionary keys from strings to integers and get this error: RuntimeError: dictionary keys changed during iteration

Question:

def load_method(self, inp_list, file):
       self.DB.global_row = -1
       # clear the widgets and listbox
       self.DB.clear_test_list()
       for item in self.DB.inp_dict:
           del item
       inp_list.delete(0, 'end')
        # THIS IS THE RELEVANT PART FOR THIS QUESTION
       [self.DB.test_dict, self.DB.inp_dict] = json.load(file)
       counter = 0
       for key in self.DB.test_dict:                       # change the keys to be integer instead of strings
           self.DB.test_dict[counter] = self.DB.test_dict[key]
           del self.DB.test_dict[key]
           counter += 1

I’m sure there is a correct way to do it, does anyone know how?

Asked By: evgeny

||

Answers:

You cannot neither modify nor remove/add keys to a dictionary while iterating over it.

A dict comprehension seems to be the best choice for your use case:

  • use zip to get values from the range you want (looks like [0,len(self.DB.test_dict)), where 0 is inclusive and the last element exclusive)

self.DB.test_dict = {counter : v for (k,v), counter in zip(self.DB.test_dict.items(), range(len(self.DB.test_dict)))}

Example:

>>> x = {"a": 1, "b":2}
>>> x = {int(counter):v for (k,v),counter in zip(x.items(), range(len(x)))}
>>> x
{0: 1, 1: 2}

Answered By: Gameplay

You’d have to create a new dictionary from your existing one. A simple pythonic way of achieving this would be by changing the code as follows:

def load_method(self, inp_list, file):
    self.DB.global_row = -1
    # clear the widgets and listbox
    self.DB.clear_test_list()
    for item in self.DB.inp_dict:
        del item
    inp_list.delete(0, 'end')
    # THIS IS THE RELEVANT PART FOR THIS QUESTION

    [self.DB.test_dict, self.DB.inp_dict] = json.load(file)
    self.DB.test_dict = {int(idx): self.DB.test_dict[key] for idx, key in enumerate(d.keys())}
Answered By: Daksh Goyal
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.