简体   繁体   中英

Python iterate nested dictionary to remove keys

I want to remove nested keys in a dictionary whose values are empty.

Example:

d = {'A': {'a': {1: [('string1', 'string2')]}}, 
     'B': {'b': {}},
     'C': {}
    }

For each of the main keys, there is a sub key and a sub sub key. If any of the key's values are empty, i want to remove the entire key.

However, i get the error : RuntimeError: dictionary changed size during iteration when i loop through the dictionary to delete empty values.

for k,v in d.iteritems():
    if not v:
        del d[k]
    else:
        for a,b in v.iteritems():
        if not b:
            del d[k][a]

desired output:

d = {'A': {'a': {1: [('string1', 'string2')]}}}

As others have pointed out, you're modifying the iterable as you iterate over it. Instead, you could make a deep copy of your dictionary to iterate over, which will allow you to edit the contents of the original datastructure.

import copy
d = {'A': {'a': {1: [('string1', 'string2')]}},
     'B': {'b': {}},
     'C': {}
    }

for k,v in copy.deepcopy(d).items():
    if not v:
        del d[k]
    else:
        for a,b in v.items():
            if not b:
                del d[k]

out:

{'A': {'a': {1: [('string1', 'string2')]}}}

You can create the identical deep copy of your dictionary. Below is the solution for the same.

import copy
d = {'A': {'a': {1: [('string1', 'string2')]}}, 
     'B': {'b': {}},
     'C': {}
    }

d2 = copy.deepcopy(d)

for k,v in d.items():
    if not v:
        del d2[k]
    else:
        for a,b in v.items():
            if not b:
                del d2[k][a]
        if not d2[k]:
            del d2[k]
print(d2)

So, d2 gives you require dict.

for k, v in d.items():

  if not v:
    del d[k]
  else:
    for a,b in v.items():
        if not b:
            if len(d[k])==1:
                del d[k][a]
                del d[k]
            else:
                del d[k][a]
print d

here is fix to your problem

old_d = {'A': {'a': {1: [('string1', 'string2')]}}, 
 'B': {'b': {}},
 'C': {}
}

new_d ={}

for k,v in old_d.iteritems():
print k
print v
if v:
    for a,b in v.iteritems():
        if b:
            new_d[k]=v
            new_d[k][a]=b
old_d = new_d
print "old_d", old_d

output: old_d {'A': {'a': {1: [('string1', 'string2')]}}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM