Home > Net >  Delete certain keys from a nested dictionary using dictionary comprehension
Delete certain keys from a nested dictionary using dictionary comprehension

Time:03-31

I have to work with a nested dictionary filled with numbers in python 'my_dict', and a list that specifies the subkeys 'keys 'that have to be deleted:

keys=[1,9]
my_dict={1:{1:a, 2:b}, 2:{1:c, 3:d, 9:e}}

I want to have two outcomes:
Delete all subkeys their values if they are in keys, e.g.

new_dict={1:{2:b}, 2:{3:d}}

Or Delete all subkeys their values if they are not in keys, e.g.

new_dict:{1:{1:a}, 2:{1:c,9:e}}

I have tried:

new_list = {outer_k: {inner_k: inner_v for inner_k, inner_v in outer_v.items()-{1,9}} for    outer_k,  outer_v in my_dict.items()}

It gives me back the same dict without deletion of the elements, same for the second szenario

new_list = {outer_k: {inner_k: inner_v for inner_k, inner_v in outer_v.items()&{1,9}} for    outer_k,  outer_v in my_dict.items()}

I have also tried:

for key, value in my_dict.items():
    for key1, value1 in value.items():
        for key1 in keys:
            try:
                 del dict[key1]
            except KeyError:
                 pass

This gives me the error:

TypeError: 'type' object does not support item deletion

I would be glad if anyone knows of a neat solution for this!

CodePudding user response:

Using dict comprehension:

new_dict = {k_out : {k_in : v_in for k_in, v_in in v_out.items() if k_in in keys} for k_out,v_out in my_dict.items()}

CodePudding user response:

The error TypeError: 'type' object does not support item deletion stems from

for key, value in my_dict.items():
    for key1, value1 in value.items():
        for key1 in keys:
            try:
                 del dict[key1]    # this is the build in, not your instance
                                   # fix:    del my_dict[key1]
            except KeyError:
                 pass

As for the comprehensions - they look rather long ....

keys = [1,9]
my_dict = {1:{1:"a", 2:"b"}, 2:{1:"c", 3:"d", 9:"e"}}


# delete top levels 
# for unwanted_key in keys:
#     try:
#         del my_dict[unwanted_key]
#     except KeyError:
#         pass

# delete inside sub levels 
for unwanted_key in keys:
    for inner_key in my_dict:
        try:
            del my_dict[inner_key][unwanted_key]
        except KeyError:
            pass

print( my_dict)

Results in

# {2: {3: 'd'}}               # if you do top level and sub level

{1: {2: 'b'}, 2: {3: 'd'}}   # if you only do sub levels

The try: ... except: ... follows "Ask forgiveness not permission" - explain

CodePudding user response:

For your example , i recreated the data to runnable, however deleting directly from the dict you' re iterating on will throw an error , you can do it by creating a copy of a dictionary where will your result will be stored

keys=[1,9]
my_dict={1:{1:"a", 2:"b"}, 2:{1:"c", 3:"d", 9:"e"}}
my_dict

new_dict1=my_dict.copy()
for key, value in my_dict.items():
    if key1 in value.keys() and key1 in keys:
          # delete subkeys and their sub values
          del new_dict1[key][key1]
          
          

CodePudding user response:

You can modify my_dict in situ like this:

keys = [1, 9]
my_dict = {1: {1: 'a', 2: 'b'}, 2: {1: 'c', 3: 'd', 9: 'e'}}
for v in my_dict.values():
    for k in keys:
        if k in v:
            del v[k]
print(my_dict)

Output:

{1: {2: 'b'}, 2: {3: 'd'}}
  • Related