Home > Net >  How to dynamically populate a nested dictionary from another dictionary
How to dynamically populate a nested dictionary from another dictionary

Time:03-25

I have a function that should convert its 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]
        })

CodePudding user response:

There may be better ways but this seems to work:

import json
dict1 = {
    'p1->a->b': 1,
    'p1->a->c': 2,
    'p1->d': 4,
    'p2->a': 3
}
d = dict()
for k, v in dict1.items():
    cd = d
    for k_ in (t := k.split('->'))[:-1]:
        if k_ not in cd:
            cd[k_] = dict()
        cd = cd[k_]
    cd[t[-1]] = v
print(json.dumps(d, indent=2))

Output:

{
  "p1": {
    "a": {
      "b": 1,
      "c": 2
    },
    "d": 4
  },
  "p2": {
    "a": 3
  }
}

Note:

The import of json is only for the pretty print at the end

CodePudding user response:

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
}
dict1_expected = {}

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

You can help my country, check my profile info.

  • Related