'Dynamically delete an item from a nested dictionary

I have a nested dictionary and I want to be able to delete an arbitrary key inside of it.

The dictionary could look like this:

D={'key1':{'key2':{'key3':'value3', 'key4':'value4'}, 'key5':'value5'}}

But it could be of arbitrary size. The problem is that the keys should be taken from a "key list" looking, for example, like this:

key_list = ['key1', 'key2', 'key4']

key_list could be of arbitrary size and have any of the dictionary's keys in it.

Because of the above criteria, I can't just use:

del D['key1']['key2']['key4']

because I can't know beforehand which keys that key_list will contain.

So, how would a generic code look like that based on the content of key_list, deletes the corresponding item in the dictionary D?



Solution 1:[1]

You can think of nested dictionaries, as a dictionary with multipart keys. If you transform your dict, then you decide when to delete an element. If part of the key is in the keylist, or any other criteria. Consider this:

D={'key1':{'key2':{'key3':'value3', 'key4':'value4', 'key7':{'key8':'value8'}}, 'key5':'value5'}, 'key6': 'value6'}

def multipart_key(d):
    dd = {}
    for k in d:
        if isinstance(d[k], dict):
            inner = multipart_key(d[k])
            for kk in inner:
                dd[k+chr(124)+kk] = inner[kk]
        else:
            dd[k] = d[k]
    return dd

key_list = ['key3', 'key7']

DD = multipart_key(D)
newDD = DD.copy()

for k in DD:
    for kk in k.split(chr(124)):
        if kk in key_list:
            del newDD[k]
            break

print(DD)
# {'key1|key2|key3': 'value3', 'key1|key5': 'value5', 'key6': 'value6', 'key1|key2|key7|key8': 'value8', 'key1|key2|key4': 'value4'}

print(newDD)
# {'key1|key5': 'value5', 'key6': 'value6', 'key1|key2|key4': 'value4'}

Solution 2:[2]

If you use NestedDict you can pop or delete any key as you would do in a flattened dictionary.

First let's initialize one:

from ndicts.ndicts import NestedDict

d = {'key1': {'key2': {'key3': 'value3', 'key4': 'value4'}, 'key5': 'value5'}}
nd = NestedDict(d)
key = ('key1', 'key2', 'key4')

Option 1

>>> del nd[key]

Option 2

>>> nd.pop(key)
'value4'

Note that this will delete an item in the original dictionary. To avoid this you can copy it when instantiating the NestedDict

nd = NestedDict(d, copy=True)

To install ndicts pip install ndicts

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 chapelo
Solution 2 edd313