Categories
dictionary python sorting

How do I sort a dictionary by value?

3416

I have a dictionary of values read from two fields in a database: a string field and a numeric field. The string field is unique, so that is the key of the dictionary.

I can sort on the keys, but how can I sort based on the values?

Note: I have read Stack Overflow question here How do I sort a list of dictionaries by a value of the dictionary? and probably could change my code to have a list of dictionaries, but since I do not really need a list of dictionaries I wanted to know if there is a simpler solution to sort either in ascending or descending order.

5

  • 9

    The dictionary data structure does not have inherent order. You can iterate through it but there’s nothing to guarantee that the iteration will follow any particular order. This is by design, so your best bet is probaly using anohter data structure for representation.

    – Daishiman

    Jul 5, 2010 at 2:08

  • 135

    “sorted()” can operate on dictionaries (and returns a list of sorted keys), so I think he’s aware of this. Without knowing his program, it’s absurd to tell someone they’re using the wrong data structure. If fast lookups are what you need 90% of the time, then a dict is probably what you want.

    – bobpaul

    Feb 15, 2013 at 19:04

  • All three outputs (keys, values, both) for sorting dictionaries are covered here in a clear and concise style: stackoverflow.com/questions/16772071/sort-dict-by-value-python

    – JStrahl

    Mar 7, 2016 at 10:14

  • 2

    @Daishiman The base class might not be ordered but OrderedDict is of course.

    Sep 9, 2017 at 1:10

  • 1

    In Python 3.6+ dictionaries preserve insertion order. This is, of course, not the same as possibility of sorting them by value, but on the other hand it is no longer valid to say that “dictionary data structure does not have inherent order”.

    Dec 31, 2018 at 13:30

6471

+500

Python 3.7+ or CPython 3.6

Dicts preserve insertion order in Python 3.7+. Same in CPython 3.6, but it’s an implementation detail.

>>> x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
>>> {k: v for k, v in sorted(x.items(), key=lambda item: item[1])}
{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}

or

>>> dict(sorted(x.items(), key=lambda item: item[1]))
{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}

Older Python

It is not possible to sort a dictionary, only to get a representation of a dictionary that is sorted. Dictionaries are inherently orderless, but other types, such as lists and tuples, are not. So you need an ordered data type to represent sorted values, which will be a list—probably a list of tuples.

For instance,

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))

sorted_x will be a list of tuples sorted by the second element in each tuple. dict(sorted_x) == x.

And for those wishing to sort on keys instead of values:

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(0))

In Python3 since unpacking is not allowed we can use

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=lambda kv: kv[1])

If you want the output as a dict, you can use collections.OrderedDict:

import collections

sorted_dict = collections.OrderedDict(sorted_x)

10

  • 49

    for timings on various dictionary sorting by value schemes: writeonly.wordpress.com/2008/08/30/…

    Mar 14, 2009 at 17:55

  • 191

    sorted_x.reverse() will give you a descending ordering (by the second tuple element)

    May 3, 2010 at 5:24

  • 488

    saidimu: Since we’re already using sorted(), it’s much more efficient to pass in the reverse=True argument.

    – rmh

    Jul 5, 2010 at 2:59

  • 128

    In python3 I used a lambda: sorted(d.items(), key=lambda x: x[1]). Will this work in python 2.x?

    – Benbob

    Feb 15, 2011 at 15:05

  • 4

    Where can I read more about the usage of key=lambda item :item[1] please? The part I don’t quite understand is the item[1], is it because when we do x.items() it returns the key-value pairs and with this we can tap into the value by doing item[1]?

    Nov 6, 2021 at 23:56


1543

As simple as: sorted(dict1, key=dict1.get)

Well, it is actually possible to do a “sort by dictionary values”. Recently I had to do that in a Code Golf (Stack Overflow question Code golf: Word frequency chart). Abridged, the problem was of the kind: given a text, count how often each word is encountered and display a list of the top words, sorted by decreasing frequency.

If you construct a dictionary with the words as keys and the number of occurrences of each word as value, simplified here as:

from collections import defaultdict
d = defaultdict(int)
for w in text.split():
    d[w] += 1

then you can get a list of the words, ordered by frequency of use with sorted(d, key=d.get) – the sort iterates over the dictionary keys, using the number of word occurrences as a sort key .

for w in sorted(d, key=d.get, reverse=True):
    print(w, d[w])

I am writing this detailed explanation to illustrate what people often mean by “I can easily sort a dictionary by key, but how do I sort by value” – and I think the original post was trying to address such an issue. And the solution is to do sort of list of the keys, based on the values, as shown above.

3

  • 38

    This is also good but key=operator.itemgetter(1) should be more scalable for efficiency than key=d.get

    – smci

    Dec 9, 2011 at 21:18

  • 12

    @bli sorted_keys = sorted(d.items(), key=itemgetter(1), reverse=True) and for key, val in sorted_keys: print "%s: %d" % (key, val) – itemgetter creates a function when it’s called, you don’t use it directly like in your example. And a plain iteration on a dict uses the keys without the values

    – Izkata

    Aug 19, 2014 at 20:21


  • 28

    i have come from the future to tell you of collections.Counter, which has a most_common method that might interest you 🙂

    – Eevee

    Jun 25, 2017 at 20:47

1087

You could use:

sorted(d.items(), key=lambda x: x[1])

This will sort the dictionary by the values of each entry within the dictionary from smallest to largest.

To sort it in descending order just add reverse=True:

sorted(d.items(), key=lambda x: x[1], reverse=True)

Input:

d = {'one':1,'three':3,'five':5,'two':2,'four':4}
a = sorted(d.items(), key=lambda x: x[1])    
print(a)

Output:

[('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]

6

  • From what I’ve seen (docs.python.org/2/library/…), there is a class called OrderedDict which can be sorted and retain order whilst still being a dictionary. From the code examples, you can use lambda to sort it, but I haven’t tried it out personally 😛

    Feb 20, 2013 at 10:38

  • 70

    I’d prefer key=lambda (k, v): v personally

    – Claudiu

    Apr 9, 2015 at 23:08


  • @Keyo shouldn’t that be it returns an ordered list of keys (sorted by values) not (k,v) tuples? That’s what I get with Python 2.7.10. @Nyxynyx add the parameter reverse=True to sort in descending order.

    – dhj

    Nov 16, 2015 at 16:49

  • 48

    @Claudiu I like that (k, v) syntax too, but it’s not available in Python 3 where tuple parameter unpacking was removed.

    – Bob Stein

    Feb 5, 2016 at 17:53

  • 1

    If you wrap this in an OrderedDict() instance you will get a (ordered) dict instead of list of tuples!

    Mar 21, 2019 at 10:30