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:
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 record Employee = { 'emp1' : { 'name' : 'Lisa' , 'age' : '29' , 'Designation' : 'Programmer' }, 'emp2' : { 'name' : 'Steve' , 'age' : '45' , 'Designation' : 'HR' } } # updating in the way similar to # simple dictionary Employee[ '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 record Employee = { 'emp1' : { 'name' : 'Lisa' , 'age' : '29' , 'Designation' : 'Programmer' }, 'emp2' : { 'name' : 'Steve' , 'age' : '25' , 'Designation' : 'HR' } } # updating in the way similar to simple dictionary Employee[ '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 record Employee = { 'emp1' : { 'name' : 'Lisa' , 'age' : '29' , 'Designation' : 'Programmer' }, 'emp2' : { 'name' : 'Steve' , 'age' : '25' , 'Designation' : 'HR' } } # updating in the way similar to # simple dictionary Employee[ 'emp1' ][ 'name' ] = 'Kate' # adding new key-value pair to first # employee record Employee[ '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 record Employee = { '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 update empid = input ( "Employee id :" ) # which attribute / key to update attribute = input ( "Attribute to be updated :" ) # what value to update new_value = input ( "New value :" ) # updation of the dictionary Employee[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 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 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 flatten from flatten_dict import unflatten # an employee record Employee = { '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 record dict3[( '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}}