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 key argument, we tell .sorted() what data will be used to sort the .items() tuples.
  • x is 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 = tuple
  • x[1] = tuple value (the 2nd element of the tuple), which is the level 2 dict
  • x[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 = tuple
  • x[1] = tuple value, the level 2 dict
  • x[1]['l2_k1'] = level3 dict
  • x[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'])