7

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?

6
  • are you sure about the order of your key_list and if you want to delete the corresponding item it doesn't raise KeyError ! Commented Nov 27, 2014 at 21:12
  • No KeyError for me no. Commented Nov 27, 2014 at 21:16
  • Two questions which might crystalize the problem in my mind: 1) Is the intent each time to remove a single key/value pair from the dictionary? 2) Is the sequence in which keys appear in key_list significant? I suppose the second question is much like what @Kasra is asking. Commented Nov 27, 2014 at 21:16
  • In your example, do you intend to treat the keys as a path to a deeply nested element in the dict and hence only delete the leaf? Or do you intend to delete every element whose key is given in your key_list? Commented Nov 27, 2014 at 21:19
  • One additional question - can distinct keys appear multiple times in the dictionary (in different "levels", so to speak)? For example, D = {'key1':{'key1':'value1', 'key2':'value2'}} Commented Nov 27, 2014 at 21:20

3 Answers 3

7

You can use a for-loop to go through the values in key_list and navigate to the sub-dictionary that you want to remove the item from:

sub = D                 # Start with the full dictionary
for i in key_list[:-1]:
    sub = sub[i]        # Move down a level

In the end, sub will be the dictionary that you want to alter. All you need to do now is:

del sub[key_list[-1]]

since key_list[-1] is the key to remove.

Below is a demonstration:

>>> D={'key1':{'key2':{'key3':'value3', 'key4':'value4'}, 'key5':'value5'}}
>>> key_list = ['key1', 'key2', 'key4']
>>> sub = D
>>> for i in key_list[:-1]:
...     sub = sub[i]
...
>>> del sub[key_list[-1]]
>>> D
{'key1': {'key5': 'value5', 'key2': {'key3': 'value3'}}}
>>>

As you can see, this is equivalent to:

>>> D={'key1':{'key2':{'key3':'value3', 'key4':'value4'}, 'key5':'value5'}}
>>> del D['key1']['key2']['key4']
>>> D
{'key1': {'key5': 'value5', 'key2': {'key3': 'value3'}}}
>>>

except that the solution is dynamic (no hard-coded keys).

Sign up to request clarification or add additional context in comments.

1 Comment

It seem to work great! I didn't realise sub could affect D, nice solution.
0

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'}

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.