1

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?

1
  • Why are nested dictionaries so popular on stackoverflow? What is that good for? Commented Sep 4, 2018 at 17:13

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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?

2 Comments

The problem with that is that I do not know the level of nesting in my initial dictionary. Correct me if I am wrong. Happy to learn.
Sure you do: it's right there in the dictionary structure. Traverse the tree, one level at a time. However, if your mind already handles recursion, I recommend you follow the answer you already chose; it's where my hints should lead you, eventually.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.