Creating a nested dictionary from a flattened dictionary

后端 未结 7 2048
-上瘾入骨i
-上瘾入骨i 2020-12-15 02:43

I have a flattened dictionary which I want to make into a nested one, of the form

flat = {\'X_a_one\': 10,
        \'X_a_two\': 20, 
        \'X_b_one\': 10,         


        
7条回答
  •  猫巷女王i
    2020-12-15 03:16

    Here's one way using collections.defaultdict, borrowing heavily from this previous answer. There are 3 steps:

    1. Create a nested defaultdict of defaultdict objects.
    2. Iterate items in flat input dictionary.
    3. Build defaultdict result according to the structure derived from splitting keys by _, using getFromDict to iterate the result dictionary.

    This is a complete example:

    from collections import defaultdict
    from functools import reduce
    from operator import getitem
    
    def getFromDict(dataDict, mapList):
        """Iterate nested dictionary"""
        return reduce(getitem, mapList, dataDict)
    
    # instantiate nested defaultdict of defaultdicts
    tree = lambda: defaultdict(tree)
    d = tree()
    
    # iterate input dictionary
    for k, v in flat.items():
        *keys, final_key = k.split('_')
        getFromDict(d, keys)[final_key] = v
    
    {'X': {'a': {'one': 10, 'two': 20}, 'b': {'one': 10, 'two': 20}},
     'Y': {'a': {'one': 10, 'two': 20}, 'b': {'one': 10, 'two': 20}}}
    

    As a final step, you can convert your defaultdict to a regular dict, though usually this step is not necessary.

    def default_to_regular_dict(d):
        """Convert nested defaultdict to regular dict of dicts."""
        if isinstance(d, defaultdict):
            d = {k: default_to_regular_dict(v) for k, v in d.items()}
        return d
    
    # convert back to regular dict
    res = default_to_regular_dict(d)
    

提交回复
热议问题