How to dynamically populate a nested dictionary from another dictionary

Question:

I have a function that should convert it’s input dictionaries into their correct format. Keys of each input dictionary contains one or more -> to indicate nested structure.

dict1 = {
    'p1->a->b': 1,
    'p1->a->c': 2,
    'p1->d': 4,
    'p2->a': 3
}
dict1_expected = {
    'p1': {
        'a': {
            'b': 1,
            'c': 2
        },
        'd': 4
    },
    'p2': {
        'a': 3
    }
}

def foo(input_dict):
    # Process input_dict
    return input dict

assert dict1_expected == foo(dict1)

Right now I can do this only one level deep in the following way:

dict1_expected = {}
for param in dict1:
    if param.split("->")[0] not in dict1_expected:
        dict1_expected.update({
            param.split("->")[0]: {
                param.split("->")[1]: dict1[param]
            }
        })
    else:
        dict1_expected[param.split("->")[0]].update({
            param.split("->")[1]: dict1[param]
        })
Asked By: bbasaran

||

Answers:

It’s easier to make it using nested loop. Outer loop iterates over key-value pairs of dict1, inner loop iterate over splitted by -> key.

Code:

dict1 = {
    'p1->a->b': 1,
    'p1->a->c': 2,
    'p1->d': 4,
    'p2->a': 3,
    'c': 0
}
dict1_expected = {}

for key, value in dict1.items():
    current_dict = dict1_expected
    *parts, last = key.split('->')
    for part in parts:
        if part not in current_dict:
            current_dict[part] = {}
        current_dict = current_dict[part]
    current_dict[last] = value

Result:

{
    'p1': {
        'a': {
            'b': 1, 
            'c': 2
        }, 
        'd': 4
    }, 
    'p2': {
        'a': 3
    }, 
    'c': 0
}
Answered By: Olvin Roght

I came up with this:

def foo(input_dict):
    # Process input_dict
    res = {}
    for path, value in input_dict.items():
        curr = res
        components = path.split('->')
        for c in components[:-1]:
            curr = curr.setdefault(c, {})

        curr[components[-1]] = value

    return res
Answered By: Guy
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.