Python: Update Nested Dictionary

14 May, 2020
A Dictionary in Python works similar to the Dictionary in the real world. Keys of a Dictionary must be unique and of immutable data types such as Strings, Integers, and tuples, but the key-values can be repeated and be of any type.
Refer to the below article to get the idea about dictionaries:
Python Dictionary
Nested Dictionary: The nested dictionaries in Python are nothing but dictionaries within a dictionary.
Consider an employee record as given below :
Employees
emp1:
     name:Lisa
     age:29
     designation:Programmer
emp2:
     name:Steve
     age:45
     designation:HR

Here, the employees is the outer dictionary. emp1, emp2 are keys that have another dictionary as their value. The dictionary structure of the above information appears as :
employees:
{
 emp1:
    {
     'name':'Lisa',
     'age':29,
     'designation':'Programmer'
    },
emp2:
    {
     'name':'Steve',
     'age':45,
     'designation':'HR'
    }
}

Consider a simple dictionary like d={'a':1, 'b':2, 'c':3}. If you want to update the value of ‘b’ to 7, you can write as d['b']=7. However the same method cannot be applied to nested ones. That will create a new key as the keys in outer dictionary will only be searched while you try to update. For example, see the code below:
# an employee recordEmployee = {     'emp1': {        'name': 'Lisa',         'age': '29',        'Designation':'Programmer'            },     'emp2': {             'name': 'Steve',             'age': '45',             'Designation':'HR'             }}   # updating in the way similar to# simple dictionaryEmployee['name']='Kate'  print(Employee)
{‘name’: ‘Kate’, ’emp1′: {‘Designation’: ‘Programmer’, ‘name’: ‘Lisa’, ‘age’: ’29’}, ’emp2′: {‘Designation’: ‘HR’, ‘name’: ‘Steve’, ‘age’: ’45’}}
In the output look that ‘name’:’Kate’ is added as a new key-value pair which is not our desired output. Let us consider that we need to update first employee’s name as ‘Kate’. Let us look at our dictionary as a 2D-array. This will help us update the information easily. The 2D-array view of the above dictionary is given below:
Employee     name        age      Designation
emp1         Lisa         29       Programmer
emp2         Steve        45       HR

Now we have to update the first employee’s name as ‘Kate’. So we have to update Employee[’emp1′][‘name’]. The modified code is given below:
# an employee recordEmployee = {     'emp1': {        'name': 'Lisa',         'age': '29',        'Designation':'Programmer'            },          'emp2': {             'name': 'Steve',             'age': '25',             'Designation':'HR'                 }             }   # updating in the way similar to simple dictionaryEmployee['emp1']['name']='Kate'  print(Employee)
{’emp2′: {‘Designation’: ‘HR’, ‘age’: ’25’, ‘name’: ‘Steve’}, ’emp1′: {‘Designation’: ‘Programmer’, ‘age’: ’29’, ‘name’: ‘Kate’}}
The above method updates the value for the mentioned key if it is present in the dictionary. Otherwise, it creates a new entry. For example if you want to add a new attribute ‘salary’ for the first employee, then you can write the above code as :
# an employee recordEmployee = {     'emp1': {        'name': 'Lisa',         'age': '29',        'Designation':'Programmer'            },          'emp2': {             'name': 'Steve',             'age': '25',             'Designation':'HR'                 }             }   # updating in the way similar to # simple dictionaryEmployee['emp1']['name']='Kate'  # adding new key-value pair to first # employee recordEmployee['emp1']['salary']= 56000  print(Employee)
{’emp1′: {‘Designation’: ‘Programmer’, ‘salary’: 56000, ‘name’: ‘Kate’, ‘age’: ’29’}, ’emp2′: {‘Designation’: ‘HR’, ‘name’: ‘Steve’, ‘age’: ’25’}}
The above methods are static. Now to make it interactive with the user, we can slightly modify the code as given below:
# an employee recordEmployee = {     'emp1': {        'name': 'Lisa',         'age': '29',        'Designation':'Programmer'            },          'emp2': {             'name': 'Steve',             'age': '25',             'Designation':'HR'                 }             }   # to make the updation dynamic  # Get input from the user for which # employee he needs to updateempid = input("Employee id :")  # which attribute / key to updateattribute = input("Attribute to be updated :")  # what value to updatenew_value = input("New value :")  # updation of the dictionaryEmployee[empid][attribute]= new_value    print(Employee)
Employee id :emp1
Attribute to be updated :name
New value :Kate

{’emp1′: {‘age’: ’29’, ‘Designation’: ‘Programmer’, ‘name’: ‘Kate’}, ’emp2′: {‘age’: ’25’, ‘Designation’: ‘HR’, ‘name’: ‘Steve’}}
Let us try to be a bit more professional!!
An alternative approach
The idea is to flatten the nested dictionary first, then update it and unflatten it again. To make it more clear, consider the following dictionary as an example:
dict1={
       'a':{
            'b':1
           },
        'c':{
            'd':2,
            'e':5
             }
       }

Flattening a nested dictionary is nothing but appending the parent key with the real key using appropriate separators. The separator can be any symbol. It can be a comma(, ), or a hyphen(-), or an underscore(_), or a period(.), or even just a space( ). Here, after flattening with underscore as the separator, this dictionary will look like :
dict1={'a_b':1, 'c_d':2, 'c_e':5}

The flattening can be easily done with the in-built methods provided by the package flatten-dict in Python. It provides methods for flattening dictionary like objects and unflattening them. Install the package using the pip command as below:
pip install flatten-dict
flatten() method:
The flatten method has various arguments to format it in a desirable, readable and understandable way. The two most important arguments among all is:
dict : The flattened dictionary which has to be convertedreducer : It specifies how the parent key is joined with the child. The values possible are tuple, path, underscore or a user defined function name.tuple: creates a tuple of parent and child keys as the key and assigns the value to it.path : Appends ‘/’ between the parent and child key.underscore: Appends ‘_’ between the parent and child key.User defined function: The parent and child key should be passed to the function as arguments. The function should return them as a string separated by desired symbol
dict : The flattened dictionary which has to be converted
reducer : It specifies how the parent key is joined with the child. The values possible are tuple, path, underscore or a user defined function name.
tuple: creates a tuple of parent and child keys as the key and assigns the value to it.
path : Appends ‘/’ between the parent and child key.
underscore: Appends ‘_’ between the parent and child key.
User defined function: The parent and child key should be passed to the function as arguments. The function should return them as a string separated by desired symbol
Other arguments enumerate_types, keep_empty_types are optional
unflatten() method:
This method unflattens the flattened dictionary and converts it into a nested one. It can take three arguments :
dict : The flattened dictionary which has to be revertedsplitter : The symbol on which the flattened dictionary has to be split. Like flatten method, this also takes up the value tuple, path, underscore or a user defined function.inverse : Takes a boolean value indicating whether key and value has to be inverted. This is optional.
dict : The flattened dictionary which has to be reverted
splitter : The symbol on which the flattened dictionary has to be split. Like flatten method, this also takes up the value tuple, path, underscore or a user defined function.
inverse : Takes a boolean value indicating whether key and value has to be inverted. This is optional.
Let us consider the same Employee example we tried above. The code is given below:
from flatten_dict import flattenfrom flatten_dict import unflatten  # an employee recordEmployee = {     'emp1': {        'name': 'Lisa',         'age': '29',        'Designation':'Programmer'            },          'emp2': {             'name': 'Steve',             'age': '25',             'Designation':'HR'                 }             }   # flattening the dictionary, default # reducer is 'tuple'dict3 = flatten(Employee)  print("Flattened dictionary :", dict3)  # adding new key-value pair to second # employee's recorddict3[('emp2', 'salary')]= 34000  print(dict3)  # unflattening the dictionary, default # splitter is 'tuple'Employee = unflatten(dict3)  print("\nUnflattened and updated dictionary :", Employee)
Output:
Flattened dictionary : {(’emp1′, ‘name’): ‘Lisa’, (’emp1′, ‘age’): ’29’, (’emp1′, ‘Designation’): ‘Programmer’, (’emp2′, ‘name’): ‘Steve’, (’emp2′, ‘age’): ’25’, (’emp2′, ‘Designation’): ‘HR’}{(’emp1′, ‘name’): ‘Lisa’, (’emp1′, ‘age’): ’29’, (’emp1′, ‘Designation’): ‘Programmer’, (’emp2′, ‘name’): ‘Steve’, (’emp2′, ‘age’): ’25’, (’emp2′, ‘Designation’): ‘HR’, (’emp2′, ‘salary’): 34000}
Unflattened and updated dictionary : {’emp1′: {‘name’: ‘Lisa’, ‘age’: ’29’, ‘Designation’: ‘Programmer’}, ’emp2′: {‘name’: ‘Steve’, ‘age’: ’25’, ‘Designation’: ‘HR’, ‘salary’: 34000}}
python-dict
Python-nested-dictionary
Python
Technical Scripter
python-dict
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.