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]
})
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
}
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
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]
})
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
}
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