Sort nested dicts in Python
In this post, we will see how to sort one to many-levels-nested dictionnaries in CPython version >= 3.7 with the sorted() function. Starting with a simple 1-level dict, to 4-levels nested dict.
One level
I want to sort the following dict by the integer value. This is the simplest case, a dict with only one level.
dico = {
"l1_key1": 2,
"l1_key2": 1,
"l1_key3": 3
}
Solution
We call sorted() with two arguments : what to move/sort, and the sorting key.
sorted(dico.items(), key=lambda x: x[1])
Details
What to sort/move :
dico.items()
Calling
.items()returns keys and values of the dict.dico.items()returns a list of tuples (actually its a "dict_items" object, but in our case it works like a list). Each tuple has 2 items : the key and the value.[('l1_key1', 2), ('l1_key2', 1), ('l1_key3', 3)]- In this exemple, the key (position
[0]of a tuple) is a string, and the value (position[1]) is an integer
What is the sorting key :
key=lambda x: x[1]
- In the sorting
keyargument, we tell.sorted()what data will be used to sort the.items()tuples. xis representing the tuples, and[1]is the position in the tuples. Remember : a tuple has 2 elements : the key (position[0]) and the value (position[1]).- So,
x[1]means that we want to sort by the value.
One more thing. Sorted will always return a list with keys as strings, and tuples as values. Just cast it to dict. The dict is our new-sorted dico, so just update it.
sorted_dico = dict(sorted(dico.items(), key=lambda x:x[1]))
dico = sorted_dico
print(dico)
{
'l1_key2': 1,
'l1_key1': 2,
'l1_key3': 3
}
Two levels
I want to sort the following dict on Level1 keys, by the value of Level2 keys2. Scroll down to the end of this post to catch a glimpse at the wanted output
dico = {
"l1_k1": {
"l2_k1": "blabla",
"l2_k2": 1
},
"l1_k2": {
"l2_k1": "blabla",
"l2_k2": 2
},
"l1_k3": {
"l2_k1": "blabla",
"l2_k2": 3
}
}
Solution
sorted(dico.items(), key=lambda x: x[1]['l2_k2'])
Details
What to sort/move : still the same way dico.items().
What is the sorting key : still with a lambda.
key=lambda x: x[1]['l2_k2']
x= tuplex[1]= tuple value (the 2nd element of the tuple), which is the level 2 dictx[1]['l2_k2']= the value of 'l2_k2' (the integer we want to sort on) inside the level 2 dict
Same thing again, we sort by the value, we cast sorted_dico to dict(), and we update dico.
sorted_dico = dict(sorted(dico.items(), key=lambda x: x[1]['l2_k2']))
dico = sorted_dico
print(dico)
{
'l1_k1': {
'l2_k1': 'blabla',
'l2_k2': 1
},
'l1_k2': {
'l2_k1': 'blabla',
'l2_k2': 2
},
'l1_k3': {
'l2_k1': 'blabla',
'l2_k2': 3
}
}
Three levels
I want to sort the following dict on Level1 keys, by the value of Level3 keys...
dico = {
"l1_k1": {
"l2_k1": {
"l3_k1": "blabla",
"l3_k2": 2
}
},
"l1_k2": {
"l2_k1": {
"l3_k1": "blabla",
"l3_k2": 1
}
},
"l1_k3": {
"l2_k1": {
"l3_k1": "blabla",
"l3_k2": 3
}
}
}
Solution
sorted(dico.items(), key=lambda x: x[1]['l2_k1']['l3_k2'])
We go deeper from level 1 into level 3 via Level2 key...
Details
What to sort/move : still dico.items().
What is the sorting key : on Level3 keys values.
key=lambda x: x[1]['l2_k1']['l3_k2']
x= tuplex[1]= tuple value, the level 2 dictx[1]['l2_k1']= level3 dictx[1]['l2_k1']['l3_k2']= integer we want to sort by
And then...
Now guess a 4th level
Yes, you got it, it's always the same logic.
sorted(dico.items(), key=lambda x: x[1]['l2_k1']['l3_k1']['l4_k1'])