juggler
juggler

Reputation: 349

How to delete from an arbitrarilly deeply nested dictionary

I have a code that uses the NestedDict class here: How can I access a deeply nested dictionary using tuples?. "I have a fully working example based on @JCash's answer:"

There are two things I would like to do with it that are causing me trouble. First, I would like to delete one of it's elements if the value of that element is zero. second, if an element is an empty dictionary because all the entries of that dictionary were deleted, I would like to delete the empty dictionary.

Using the class sited above, an example is the following:

my_tuple = (0, 1, 0, 0, 0, 1, 0, 0)
d = NestedDict()
print d
d[my_tuple] = 4
print d

#del d[my_tuple]

del d[0][1][0][0][0][1][0][0]
del d[0][1][0][0][0][1][0]
del d[0][1][0][0][0][1]
del d[0][1][0][0][0]
del d[0][1][0][0]
del d[0][1][0]
del d[0][1]
del d[0]

print d

The long list of del's is necessary in order to get rid of the multiple levels of nesting. the commented out del statement (which gives a key-error) is what I would like to implement, with a tuple of arbitrary length.

Deleting the intermediate levels shouldn't be hard once I figure out how to delete the first. I already know what I want to delete, and I can test for empty dictionaries with: if (dictionary entry) == {})

Any ideas?

Edit: Output is:

{}
{0: {1: {0: {0: {0: {1: {0: {0: 4}}}}}}}}
{}

Upvotes: 2

Views: 2962

Answers (1)

mhlester
mhlester

Reputation: 23231

Made a function deepdelete which takes a list of keys and recursively deletes the leaf, followed by any branch dictionaries that are now empty:

def deepdelete(branch, keys):
    if len(keys) > 1:                                  # not at the leaf
        empty = deepdelete(branch[keys[0]], keys[1:])  # recursion
        if empty:                                      
            del branch[keys[0]]                        # delete branch
    else:                                              # at the leaf
        del branch[keys[0]]                            # delete the leaf
    return len(branch) == 0                            # could return len

deepdelete(d, delkeys)

Passing in the dictionary you gave as example:

d = {0: {1: {0: {0: {0: {1: {0: {0: 4}}}}}}}}
deepdelete(d, (0, 1, 0, 0, 0, 1, 0, 0))

Outputs:

{}

Passing in a more interesting dictionary with other branches:

d = {0: {1: {0: {0: {0: {1: {0: {0: 4}}, 'no_delete': 2}, 'other_data': 3}, 'keep_me': 4}, 'special': 4}, 'preserve': 1}, 'important': 50}
deepdelete(d, (0, 1, 0, 0, 0, 1, 0, 0))

Outputs:

{0: {'preserve': 1, 1: {0: {0: {0: {'no_delete': 2}, 'other_data': 3}, 'keep_me': 4}, 'special': 4}}, 'important': 50}

Upvotes: 4

Related Questions