fio
fio

Reputation: 23

How to recursively remove each key from a multi-dimensional(depth not known) python dictionary?

I'm trying to test if server is OK when param is missing, by retriving a dict to remove each key from a dict:

data = {'a':'b','c':'d','e':{'aa':'bb'}}
for i in range(len(data)):    
  print "removed ans:",dict(data.items()[:i] + data.items()[i+1:])

the answer is like this:

removed ans: {'c': 'd', 'e': {'aa': 'bb', 'cc': 'dd'}}
removed ans: {'a': 'b', 'e': {'aa': 'bb', 'cc': 'dd'}}
removed ans: {'a': 'b', 'c': 'd'}

but I also need to delete each item in 'e':

removed ans: {'c': 'd', 'e': {'aa': 'bb', 'cc': 'dd'}}
removed ans: {'a': 'b', 'e': {'aa': 'bb', 'cc': 'dd'}}
removed ans: {'a': 'b', 'c': 'd'}
removed ans: {'c': 'd', 'e': {'cc': 'dd'}}
removed ans: {'a': 'b', 'e': {'aa': 'bb'}}

I think I need to do it in a function, but

  1. how can I return different answer each time in a function?

  2. how can I go to multi-demension dict?

Upvotes: 1

Views: 115

Answers (2)

LaytonGB
LaytonGB

Reputation: 1404

This can be done using a recursive generator.

data = {'a': 'b', 'c': 'd', 'e': {'aa': 'bb', 'cc': 'dd'}}

def get_next_test_data(original_data):
    for property in original_data:
        modified_data = dict(original_data)
        modified_data.pop(property)
        yield modified_data
        if isinstance(original_data[property], dict):
            for new_val in get_next_test_data(original_data[property]):
                modified_data = dict(original_data)
                modified_data[property] = new_val
                yield modified_data

for output in get_next_test_data(data):
    print(output)
print("all test cases posted")

The above code outputs:

{'c': 'd', 'e': {'aa': 'bb', 'cc': 'dd'}}
{'a': 'b', 'e': {'aa': 'bb', 'cc': 'dd'}}
{'a': 'b', 'c': 'd'}
{'a': 'b', 'c': 'd', 'e': {'cc': 'dd'}}
{'a': 'b', 'c': 'd', 'e': {'aa': 'bb'}}
"all test cases posted"

Upvotes: -1

big_bad_bison
big_bad_bison

Reputation: 1015

This can be accomplished with a recursive generator function:

def remove_next_key(my_dict):
    for key, val in my_dict.items():
        new_dict = dict(my_dict)
        if isinstance(val, dict):
            for nested_dict in remove_next_key(val):
                new_dict[key] = nested_dict
                yield new_dict
        new_dict.pop(key)
        yield new_dict

start_dict =  {'a':'b','c':'d','e':{'aa':'bb', 'cc': 'dd'}}

for sub_dict in remove_next_key(start_dict):
    print(sub_dict)

Output:

{'c': 'd', 'e': {'aa': 'bb', 'cc': 'dd'}}
{'a': 'b', 'e': {'aa': 'bb', 'cc': 'dd'}}
{'a': 'b', 'c': 'd', 'e': {'cc': 'dd'}}
{'a': 'b', 'c': 'd', 'e': {'aa': 'bb'}}
{'a': 'b', 'c': 'd'}

Upvotes: 2

Related Questions