Python | Convert flattened dictionary into nested dictionary

Given a flattened dictionary, the task is to convert that dictionary into a nested dictionary where keys are needed to be split at ‘_’ considering where nested dictionary will be started.

Method #1: Using Naive Approach

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python code to demonstrate
# conersion of flattened dictionary
# into nested dictionary
  
  
def insert(dct, lst):
    for x in lst[:-2]:
        dct[x] = dct = dct.get(x, dict())
    dct.update({lst[-2]: lst[-1]})
      
  
def convert_nested(dct):
    # empty dict to store the result
    result = dict()
  
    # create an iterator of lists 
    # representing nested or hierarchial flow
    lsts = ([*k.split("_"), v] for k, v in dct.items())
  
    # insert each list into the result
    for lst in lsts:
        insert(result, lst)
    return result
          
# initialising_dictionary
ini_dict = {'Geeks_for_for':1,'Geeks_for_geeks':4,
            'for_geeks_Geeks':3,'geeks_Geeks_for':7}
  
# priniting initial dictionary
print ("initial_dictionary", str(ini_dict))
  
# code to convert ini_dict to nested 
# dictionary splitting_dict_keys
_split_dict = [[*a.split('_'), b] for a, b in ini_dict.items()]
  
  
# printing final dictionary
print ("final_dictionary", str(convert_nested(ini_dict)))

chevron_right


Output:



initial_dictionary {‘for_geeks_Geeks’: 3, ‘Geeks_for_geeks’: 4, ‘geeks_Geeks_for’: 7, ‘Geeks_for_for’: 1}
final_dictionary {‘Geeks’: {‘for’: {‘for’: 1, ‘geeks’: 4}}, ‘for’: {‘geeks’: {‘Geeks’: 3}}, ‘geeks’: {‘Geeks’: {‘for’: 7}}}

 
Method #2: Using default dict and recursive approach

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python code to demonstrate
# conersion of flattened dictionary
# into nested dictionary
  
# code to conert dict into nested dict
def nest_dict(dict1):
    result = {}
    for k, v in dict1.items():
          
        # for each key call method split_rec which
        # will split keys to form recursively 
        # nested dictionary
        split_rec(k, v, result)
    return result
  
def split_rec(k, v, out):
      
    # splitting keys in dict
    # calling_recursively to break items on '_'
    k, *rest = k.split('_', 1)
    if rest:
        split_rec(rest[0], v, out.setdefault(k, {}))
    else:
        out[k] = v
  
          
# initialising_dictionary
ini_dict = {'Geeks_for_for':1,'Geeks_for_geeks':4,
            'for_geeks_Geeks':3,'geeks_Geeks_for':7}
  
# priniting initial dictionary
print ("initial_dictionary", str(ini_dict))
  
# printing final dictionary
print ("final_dictionary", str(nest_dict(ini_dict)))

chevron_right


Output:

initial_dictionary {‘for_geeks_Geeks’: 3, ‘Geeks_for_for’: 1, ‘Geeks_for_geeks’: 4, ‘geeks_Geeks_for’: 7}
final_dictionary {‘for’: {‘geeks’: {‘Geeks’: 3}}, ‘geeks’: {‘Geeks’: {‘for’: 7}}, ‘Geeks’: {‘for’: {‘for’: 1, ‘geeks’: 4}}}

 
Method #3: Using reduce and getitem

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python code to demonstrate
# conersion of flattened dictionary
# into nested dictionary
  
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()
  
# conerting default_dict_to regular dict
def default_to_regular(d):
      
    """Convert nested defaultdict to regular dict of dicts."""
    if isinstance(d, defaultdict):
        d = {k: default_to_regular(v) for k, v in d.items()}
    return d
          
# initialising_dictionary
ini_dict = {'Geeks_for_for':1,'Geeks_for_geeks':4,
            'for_geeks_Geeks':3,'geeks_Geeks_for':7}
  
# priniting initial dictionary
print ("initial_dictionary", str(ini_dict))
  
  
# code to convert ini_dict to nested dictionary
# iterating_over_dict
for k, v in ini_dict.items():
      
    # splitting keys
    * keys, final_key = k.split('_')
    getFromDict(d, keys)[final_key] = v
  
# printing final dictionary
print ("final_dictionary", str(default_to_regular(d)))

chevron_right


Output:

initial_dictionary {‘Geeks_for_for’: 1, ‘Geeks_for_geeks’: 4, ‘for_geeks_Geeks’: 3, ‘geeks_Geeks_for’: 7}
final_dictionary {‘Geeks’: {‘for’: {‘geeks’: 4, ‘for’: 1}}, ‘geeks’: {‘Geeks’: {‘for’: 7}}, ‘for’: {‘geeks’: {‘Geeks’: 3}}}



My Personal Notes arrow_drop_up

Programming freaktech Enthusiast and have interest in learning new upcoming technologies

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.