-1

I have the following data from a dictionary in python.

The problem that I am facing is the empty string as key and value in the dictionary.

data = {'id': '213', 'first_name': 'john', 'last_name': 'doe', '': ''}

my goal is to delete the empty string key and create a new dictionary without it

so I tried:

from copy import deepcopy


for x, y in data.items():
  if x == "":
    del data[x]

new_data = deepcopy(data)

print(new_data)

but for some reason, I am getting the following error

...
for x, y in data.items():
RuntimeError: dictionary changed size during iteration

am I missing something?

jperezmartin
  • 407
  • 4
  • 19
John D
  • 285
  • 3
  • 22
  • 2
    Why would you use a loop at all? `if "" in data: del data[""]` - done. – l4mpi Sep 16 '21 at 14:35
  • You are missing something by not reading the error message. When you delete a dictionary element, you are changing the size of the dictionary, which you should not do while you are iterating over it. You could just say `del data[""]` without the loop. – RufusVS Sep 16 '21 at 14:35
  • Why do you want a new dictionary instead of just removing that item from the one you have? – no comment Sep 16 '21 at 14:51
  • @don'ttalkjustcode i made a mistake buddy, spent too much working on javascript stuff i guess – John D Sep 16 '21 at 15:02

5 Answers5

4

Since you are already creating a deepcopy, you may benefit by simply iterating over the keys and removing the unnecessary keys with a if condition.

Try this -

new_dict = {k:v for k,v in data.items() if k!=''}
print(new_dict)
{'id': '213', 'first_name': 'john', 'last_name': 'doe'}

As the error trace mentions quite clearly, the reason for the error in the following code is because you are modifying the dictionary during iteration.

for x, y in data.items():
  if x == "":
    del data[x]            #<----

Instead, as mentioned by some other excellent answers (@tituszban), you should just use del data[''] directly.

Akshay Sehgal
  • 18,741
  • 3
  • 21
  • 51
  • 3
    You could use `dict.pop` too. Check if `key` is in `dict` then `dict.pop(key)` – Ch3steR Sep 16 '21 at 14:49
  • Note that this solution only removes the empty strings in the copy (`new_dict`), not in the original dictionary (`data`), while the code in the question tried to remove it from both lists. So the original problem is not really solved with this. – wovano Sep 17 '21 at 12:31
  • Its obvious that if the original needs to be modified, then the dict has to be saved in the original one. OP is making a deepcopy for a reason. – Akshay Sehgal Sep 18 '21 at 07:52
1

You cannot delete an item while iterating over it. But why would you? You know exactly the key you want to remove:

del data[""]

This will modify data in place. If you want to keep the original dictionary, and create a new one without the key, see @Akshay Sehgal's answer

tituszban
  • 4,797
  • 2
  • 19
  • 30
0

The error is pretty straightforward: you cannot remove elements from a dictionary (or collection in general) while iterating on it.

A better approach might be to store which items you want to delete elsewhere, and then delete them all after the iteration, instead of trying to modify the dict in the iteration itself.

In particular, for your case you can simply do something like this, which will remove the key from the dict if it exists:

del data[""]

Instead of iterating over the whole dictionary, since by definition a dictionary can have at most one entry for any key.

hoodakaushal
  • 1,253
  • 2
  • 16
  • 31
-1

To extend hoodakaushal answer you can try doing it like

from copy import deepcopy
to_delete =[]

for x, y in data.items():
  if x == "":
    to_delete.append(x)
    

for key in to_delete:
    del data[key]

new_data = deepcopy(data)

print(new_data)
user655941
  • 337
  • 3
  • 11
-3

You can try also like this if want to extract data from dictionary.

data = {'id': '213', 'first_name': 'john', 'last_name': 'doe', '': ''}
new_dict = {}
    for i, j in data.items():
        if i != "": # check key if not empty add to new dictionary
            new_dict.update({i:j})

print(new_dict)
Philip Mutua
  • 6,016
  • 12
  • 41
  • 84
Ehsan Rahi
  • 61
  • 7