Home > Mobile >  Creating a nested (resursive) dictionary in python
Creating a nested (resursive) dictionary in python

Time:01-07

For a config validation schema I need to have a nested dictionary which repeats itself. For example assume we have the following dictionary:

{
    "conf1": "x",
    "conf2": "x",
}

Now I want to have a key conf3 which contains the existing dictionary recursively for a maximum amount of iterations (i.e. 3 times) So the final result needs to look like this:

{
    "conf1": "x",
    "conf2": "x",
    "conf3": {
        "conf1": "x",
        "conf2": "x",
        "conf3": {
            "conf1": "x",
            "conf2": "x",
        }
    }
}

I tried to write a recursive function, but with this solution conf3 is repeated indefinitely

def build_nested_configuration_schema(schema: dict, iteration: int = 0) -> dict:
    iteration  = 1
    if iteration == 3:
        return schema
    schema.update({"conf3": build_nested_configuration_schema(schema, iteration)})
    return schema

new_config = build_nested_configuration_schema({"conf1": "x", "conf2": "x"})

CodePudding user response:

Based on my comment, using the copy package will disconnect the pointer reference as your example results in.

import copy
def build_nested_configuration_schema(schema: dict, iteration: int = 0) -> dict:
    internal_schema = copy.copy(schema)
    iteration  = 1
    if iteration == 3:
        return internal_schema
    schema.update({"conf3": build_nested_configuration_schema(internal_schema, iteration)})
    return schema

new_config = build_nested_configuration_schema({"conf1": "x", "conf2": "x"})
print(new_config)

Prints

{'conf1': 'x', 'conf2': 'x', 'conf3': {'conf1': 'x', 'conf2': 'x', 'conf3': {'conf1': 'x', 'conf2': 'x'}}}

The main reason this happens is with recursion, python will end up using the value in the method call as a pointer to a value, rather than a separate stored value. That is why your method does return, and does not hit a recursion max limit. The value of conf3 ends up being {conf1: x, conf2: x, conf3: } which is why debugging will show you a never ending stream of conf3 values. The copy method will work, and there may be more pythonic ways to work around the issue, but this will work if the runtime memory is not being tightly managed.

CodePudding user response:

My solution. As pypalms correctly indicates we need to make a copy of schema.

def build_nested_configuration_schema(schema: dict, iteration: int = 0) -> dict:
    iteration  = 1
    if iteration == 3:
        return schema
    schema.update({"conf3": build_nested_configuration_schema(schema.copy(), iteration)})
    return schema

CodePudding user response:

This solution uses the originally provided schema as a template and does not require recursion.

def build_nested_configuration_schema(schema: dict) -> dict:
    maxNesting = 3
    
    result = schema.copy()
    current = result
    
    for i in range(maxNesting - 1):
        next = schema.copy()
        current['conf3'] = next
        current = next

    return result

new_config = build_nested_configuration_schema({"conf1": "x", "conf2": "x"})

print(new_config)
  •  Tags:  
  • Related