You would first have to split your keys by '.'
to get the paths.
Then you can create a function that creates a nested dictionary from one path:
def make_nested_dict(iterable, final):
"""Make nested dict from iterable"""
if iterable:
head, *tail = iterable
return {head: make_nested_dict(tail, final)}
else:
return final
Which works as follows:
d = {"a.b": "foo", "a.c": "bar", "d.e.f":"baz"}
for key in d:
paths = key.split('.')
nested_path = make_nested_dict(paths, d[key])
print(nested_path)
And gives the following paths:
{'a': {'b': 'foo'}}
{'a': {'c': 'bar'}}
{'d': {'e': {'f': 'baz'}}}
Then you can create a function that merges two nested dictionaries together recursively:
def merge_nested_dicts(d1, d2):
"""Merge two nested dictionaries together"""
for key in d2:
if key in d1:
if isinstance(d2[key], dict) and isinstance(d1[key], dict):
merge_nested_dicts(d1[key], d2[key])
else:
d1[key] = d2[key]
return d1
Which you can merge by updating a resultant nested dict:
nested_dict = {}
for key in d:
paths = key.split('.')
nested_path = make_nested_dict(paths, d[key])
nested_dict = merge_nested_dicts(nested_dict, nested_path)
print(nested_dict)
And now this gives the following:
{'a': {'b': 'foo', 'c': 'bar'}, 'd': {'e': {'f': 'baz'}}}
Full code with some comments:
def make_nested_dict(iterable, final):
"""Make nested dictionary path with a final attribute"""
# If iterable, keep recursing
if iterable:
# Unpack key and rest of dict
head, *tail = iterable
# Return new dictionary, recursing on tail value
return {head: make_nested_dict(tail, final)}
# Otherwise assign final attribute
else:
return final
def merge_nested_dicts(d1, d2):
"""Merge two nested dictionaries together"""
for key in d2:
# If we have matching keys
if key in d1:
# Only merge if both values are dictionaries
if isinstance(d2[key], dict) and isinstance(d1[key], dict):
merge_nested_dicts(d1[key], d2[key])
# Otherwise assign normally
else:
d1[key] = d2[key]
return d1
if __name__ == "__main__":
d = {"a.b": "foo", "a.c": "bar", "d.e.f":"baz", "d.e.g":"M", 'l':"single_key_test" }
nested_dict = {}
for key in d:
# Create path
paths = key.split('.')
# Create nested path
nested_path = make_nested_dict(paths, d[key])
# Update result dict by merging with new dict
nested_dict = merge_nested_dicts(nested_dict, nested_path)
print(nested_dict)