How can I sort a dictionary in Python by the value of a specific sub-key in descending order?

How can I sort a dictionary in Python by the value of a specific sub-key in descending order?

I have the following dictionary d and I want to sort it based on the value of key3 in descending order:

d = { '123': { 'key1': 3, 'key2': 11, 'key3': 3 },
      '124': { 'key1': 6, 'key2': 56, 'key3': 6 },
      '125': { 'key1': 7, 'key2': 44, 'key3': 9 },
    }

After sorting, the dictionary should look like this:

d = { '125': { 'key1': 7, 'key2': 44, 'key3': 9 },
      '124': { 'key1': 6, 'key2': 56, 'key3': 6 },
      '123': { 'key1': 3, 'key2': 11, 'key3': 3 },
    }

My approach was to create another dictionary e from d, using the value of key3 as the key in e and then sorting the dictionary. However, since the value of key3 can be the same for multiple entries, I lost some keys and their values.

How can I properly sort this dictionary by the value of key3 in descending order without losing any keys or values?

Using OrderedDict: This one’s my go-to approach when I want to preserve order in the sorted dictionary.

from collections import OrderedDict

d = { '123': { 'key1': 3, 'key2': 11, 'key3': 3 },
      '124': { 'key1': 6, 'key2': 56, 'key3': 6 },
      '125': { 'key1': 7, 'key2': 44, 'key3': 9 },
    }

# Sort dictionary in descending order based on 'key3'
d_descending = OrderedDict(sorted(d.items(), key=lambda kv: kv[1]['key3'], reverse=True))

In this solution, d_descending will contain the dictionary sorted by the values of key3 in descending order. The OrderedDict ensures that the order is preserved. This method works perfectly when order retention matters.

That’s a solid way, Charity! Another neat trick is to avoid creating a new dictionary altogether and just use sorted() when iterating. This is handy when you want to process the items directly without extra overhead.

d = { '123': { 'key1': 3, 'key2': 11, 'key3': 3 },
      '124': { 'key1': 6, 'key2': 56, 'key3': 6 },
      '125': { 'key1': 7, 'key2': 44, 'key3': 9 },
    }

# Iterate over sorted dictionary based on 'key3' in descending order
for key, value in sorted(d.items(), key=lambda kv: kv[1]['key3'], reverse=True):
    do_something_with(key, value)

This approach skips modifying the dictionary itself and gets the job done right in the loop. Clean, efficient, and no need for an additional data structure.

Great points, Charity and Devan! Let me add another angle to this. If you’re looking for the top n elements based on key3 in descending order, you can use heapq.nlargest(). It’s incredibly efficient for that specific purpose.

import heapq

d = { '123': { 'key1': 3, 'key2': 11, 'key3': 3 },
      '124': { 'key1': 6, 'key2': 56, 'key3': 6 },
      '125': { 'key1': 7, 'key2': 44, 'key3': 9 },
    }

# Get the top 2 items sorted by 'key3' in descending order
top_n = heapq.nlargest(2, d.items(), key=lambda kv: kv[1]['key3'])

This solution shines when you’re dealing with a large dictionary but only care about a small subset of the highest-ranked items. Why sort the entire dictionary when you only need the top n? heapq.nlargest() nails that efficiency!