简体   繁体   中英

Creating nested dictionary in python with repeating keys

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?

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.

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM