2

I have a nested dictionary, i.e.

a={'k1':{'k2':1}}

I would like to write a function

def f(dictionary,key_list):
      pass

such that f(a,['k1','k2']) would be equivalent to del(a['k1']['k2'])

I tried to use

from functools import reduce
import operator

def f(dictionary,key_list):
     reduce(operator.delitem,key_list,dictionary)

However

f(a,['k1','k2'])

returns

TypeError: 'NoneType' object does not support item deletion
1
  • operator.delitem returns None. Commented Dec 20, 2017 at 17:47

2 Answers 2

4

You only want to delete from the innermost dictionary, not from the outer dictionaries. So for the path to get to the innermost dictionary you need to use getitem, not delitem. Only the last key should be used for deletion:

def f(dictionary, key_list):
    *path, key = key_list
    del reduce(operator.getitem, path, dictionary)[key]

Demo (with one more level to be clearer):

from functools import reduce
import operator

def f(dictionary, key_list):
    *path, key = key_list
    del reduce(operator.getitem, path, dictionary)[key]

a = {'k1': {'k2': {'k3': 1}}}
f(a, ['k1', 'k2', 'k3'])
print(a)

That prints {'k1': {'k2': {}}}, same as after del a['k1']['k2']['k3']:

a = {'k1': {'k2': {'k3': 1}}}
del a['k1']['k2']['k3']
print(a)
Sign up to request clarification or add additional context in comments.

Comments

4

I would reduce on dict.get over all but the last key to find the inner-most dictionary, then invoke del on that dict using the final key.

def f(dictionary,key_list):
    dictionary = reduce(dict.get, key_list[0:-1], dictionary)
    del dictionary[key_list[-1]]


a={'k1':{'k2':1}}
print(a)
f(a,['k1','k2'])
print(a)

Result:

$ python x.py 
{'k1': {'k2': 1}}
{'k1': {}}

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.