Reputation: 1037
I have the following dictionary:
d = {
'results.household.land_tenure_access_restitution.has_land_allocated_relation': ['false', 'true'],
"results.household.land_tenure_access_restitution.is_status_of_claim_required": ["false", "true"]
}
I need to create the following:
d2 = {
'results': {
'household': {
'land_tenure_access_restitution': {
'is_status_of_claim_required': ['false', 'true'],
'has_land_allocated_relation': ['false', 'true']
}
}
}
}
I have written the following code:
f = {}
g = {}
for key, value in d.iteritems():
print f
for n, k in enumerate(reversed(key.split('.'))):
if n == 0:
f = {k: d[key]}
else:
f = {k: f}
g.update(f)
However, the dictionary gets overwritten with the latest key value, since the upper-level key is not unique. I get this output:
{
'results': {
'household': {'land_tenure_access_restitution': {
'has_land_allocated_relation': ['false', 'true']
}}}}
How do I achieve the above-mentioned result?
Upvotes: 1
Views: 441
Reputation: 77837
You're updating far too late in your process: note that your update can happen only when you've traversed the entire string, and are back at the top level of the dict. Any time the root matches, you replace the entire tree.
You need to start at the tree's root results
and traverse downward until you detect the need to update, a difference in the existing structure versus the current string. Then you parse the remaining string and build the sub-tree to add, updating when you've reached the end of the string.
Is that sufficient hint for you to do the coding?
Upvotes: 1
Reputation: 61910
You could recursively merge the dictionary:
from functools import reduce
import collections
d = {
'results.household.land_tenure_access_restitution.has_land_allocated_relation': ['false', 'true'],
"results.household.land_tenure_access_restitution.is_status_of_claim_required": ["false", "true"]
}
def dict_merge(dct, merge_dct):
for key, value in merge_dct.items():
if key in dct and isinstance(dct[key], dict) and isinstance(merge_dct[key], collections.Mapping):
dict_merge(dct[key], merge_dct[key])
else:
dct[key] = merge_dct[key]
result = {}
for k, v in d.items():
elements = [v] + list(reversed(k.split('.')))
nested = reduce(lambda x, y: {y: x}, elements)
dict_merge(result, nested)
print(result)
Output
{'results': {'household': {'land_tenure_access_restitution': {'has_land_allocated_relation': ['false', 'true'], 'is_status_of_claim_required': ['false', 'true']}}}}
The function dict_merge
merge two dictionaries recursively, the lines:
elements = [v] + list(reversed(k.split('.')))
nested = reduce(lambda x, y: {y: x}, elements)
create a nested dictionary for each of the keys of the original dictionary.
Upvotes: 2