1

I've searched around for the error it gives me, but I don't understand that quite well. They did something with for k, v in dbdata.items, but that didn't work for me neither, it gives me other errors.

Well, I want is to delete multiple items.

tskinspath = ['1', '2']   

#
dbdata = {}
dbdata['test'] = {}
dbdata['test']['skins_t'] = {}

# Adds the items
dbdata['test']['skins_t']['1'] = 1
dbdata['test']['skins_t']['2'] = 0
dbdata['test']['skins_t']['3'] = 0
dbdata['test']['skins_t']['4'] = 0

# This doesn't work
for item in dbdata["test"]["skins_t"]:

     if item not in tskinspath:

        if dbdata["test"]["skins_t"][item] == 0:

                    del dbdata["test"]["skins_t"][item]

# exceptions.RunetimeError: dictonary changed size during iteration
tshepang
  • 12,111
  • 21
  • 91
  • 136

3 Answers3

1

Instead of iterating over the dictionary, iterate over dict.items():

for key, value in dbdata["test"]["skins_t"].items():
     if key not in tskinspath:
        if value == 0:
            del dbdata["test"]["skins_t"][key]

On py3.x use list(dbdata["test"]["skins_t"].items()).

Alternative:

to_be_deleted = []
for key, value in dbdata["test"]["skins_t"].iteritems():
     if key not in tskinspath:
        if value == 0:
            to_be_deleted.append(key)
for k in to_be_deleted: 
    del dbdata["test"]["skins_t"][k]
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • So this is faster than the first answer, if there is a lot of data's or better? Just want to make sure I use the most accurate answer. –  Oct 07 '13 at 11:05
  • This works in Python2 (where `items()` returns a list), but not in Python3 (where `items()` returns a view of the underlying dictionary). I don't know what SO policy is on which version of Python should be assumed when the questioner doesn't say. – Steve Jessop Oct 07 '13 at 11:08
  • @Frederik `items()` will return a list a of key,value pairs and `set(set(dbdata['test']['skins_t']))` would return a `set` of keys.So, in terms of memory set would be more efficient. – Ashwini Chaudhary Oct 07 '13 at 11:12
  • @Frederik I've added another solution, this one would take lesser memory. – Ashwini Chaudhary Oct 07 '13 at 11:20
0

The error message says it: you shouldn't modify the dictionary that you are iterating over. Try

for item in set(dbdata['test']['skins_t']):
   ...

This way you are iterating over a set that contains all keys from dbdata['test']['skins_t'].

Lev Levitsky
  • 63,701
  • 20
  • 147
  • 175
  • Why does it tell me that is it because of security reasons? + P.S This is a question out of the box. I just want to make sure I use that correcly as well There no different between `if item not in tskinspath:` `if not item in tskinspath:` What to use? –  Oct 07 '13 at 11:02
  • @Frederik `not in` is more human-readable and unambiguous in terms of precedence. It should be used. – Lev Levitsky Oct 07 '13 at 11:06
  • @Frederik http://stackoverflow.com/questions/17659303/what-is-more-pythonic-for-not – Ashwini Chaudhary Oct 07 '13 at 11:06
0

As the question details is way aside from the question, If you are looking for a solution that deletes multiple keys from a given dict use this snippet

[s.pop(k) for k in list(s.keys()) if k not in keep]

Additionally, you can create a new dict via comprehension.

new_dict = { k: old_dict[k] for k in keep }
nehem
  • 12,775
  • 6
  • 58
  • 84