Python sort dict by value


Whilst I found the accepted answer useful, I was also surprised that it hasn't been updated to reference OrderedDict from the standard library collections module as a viable, modern alternative - designed to solve exactly this type of problem.

from operator import itemgetter
from collections import OrderedDict

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

The official OrderedDict documentation offers a very similar example too, but using a lambda for the sort function:

# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
# OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

It is not possible to sort a dict, only to get a representation of a dict that is sorted. Dicts are inherently orderless, but other types, such as lists and tuples, are not. So you need a sorted representation, 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))


 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 How do I sort a list of dictionaries by values of the dictionary in Python? 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.

share improve this question
 
4 
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 '10 at 2:08
57 
"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 '13 at 19:04
2 
For those suggesting that this is a duplicate of stackoverflow.com/questions/72899/… , that question is marked as a duplicate of this question. –  Marcin  Sep 18 '13 at 16:36
3 
If possible, instantiate a NumPy Series from the dictionary and sort it using pandas.Series.order –  Dror  Nov 27 '14 at 14:22

34 Answers

1 2 next
up vote 1903 down vote accepted
+500

It is not possible to sort a dict, only to get a representation of a dict that is sorted. Dicts are inherently orderless, but other types, such as lists and tuples, are not. So you need a sorted representation, 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))
share improve this answer
 
23 
for timings on various dictionary sorting by value schemes:  writeonly.wordpress.com/2008/08/30/… –  Gregg Lind  Mar 14 '09 at 17:55
59 
sorted_x.reverse() will give you a descending ordering (by the second tuple element) –  saidimu May 3 '10 at 5:24
176 
saidimu: Since we're already using sorted(), it's much more efficient to pass in the reverse=Trueargument. –  rmh  Jul 5 '10 at 2:59
57 
In python3 I used a lambda: sorted(d.items(), key=lambda x: x[1]). Will this work in python 2.x? –  Keyo  Feb 15 '11 at 15:05
53 
OrderedDict added to collections in 2.7. Sorting example shown at: docs.python.org/library/… –  monkut  Apr 24 '11 at 6:31 

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 list of the top words, sorted by decreasing frequency. 

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

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

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

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

I am writing this detailed explanation to illustrate what do people often mean by "I can easily sort a dictionary by key, but how do I sort by value" - and I think the OP 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.

share improve this answer
 
10 
This is also good but key=operator.itemgetter(1) should be more scalable for efficiency than key=d.get –  smci  Dec 9 '11 at 21:18
3 
You will first need to: import collections # to use defaultdict –  rjurney  Apr 12 '13 at 23:13 
3 
@raylu I do observe a "does not work" behaviour using itemgetter: -----  from operator import itemgetter d = {"a":7, "b":1, "c":5, "d":3} sorted_keys = sorted(d, key=itemgetter, reverse=True) for key in sorted_keys: print "%s: %d" % (key, d[key]) ----- -> b: 1 c: 5 a: 7 d: 3 The results change each time I run the code: weird. (sorry, can't get the code to display properly) –  bli  Aug 13 '14 at 15:58 
3 
@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 '14 at 20:21 

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.

share improve this answer
 
32 
+1 For being the cleanest solution. However it doesn't sort the dictionary (hash table, not possible), rather it returns an ordered list of (key, value) tuples. –  Keyo  Feb 15 '11 at 15:10 
1 
@Keyo I'm new to python and came across the need to sort a dictionary. And I want to make sure I understood you well: there is no way to use lambda to sort a dictionary, right? –  lv10  Jan 9 '13 at 4:20
14 
I'd prefer key=lambda (k, v): v personally –  Claudiu  Apr 9 '15 at 23:08 
4 
@Claudiu I like that (k, v) syntax too, but it's not available in Python 3 where tuple parameter unpackingwas removed. –  BobStein-VisiBone  Feb 5 at 17:53

Dicts can't be sorted, but you can build a sorted list from them.

A sorted list of dict values:

sorted(d.values())

A list of (key, value) pairs, sorted by value:

from operator import itemgetter
sorted(d.items(), key=itemgetter(1))
share improve this answer
 
5 
+1: sorted(d.values()) is easier to read/understand than Nas's sorted(dict1, key=dict1.get), and therefore more Pythonic. About readability, please also consider my namedtuple suggestion. –  Remi  Aug 30 '11 at 23:42
12 
@Remi, those are two different things! sorted(d.values()) returns sorted list of the values from the dictionary, where sorted(d, key=d.get) returns list of the keys, sorted in order of the values! Way different. If you don't see the need for the latter, read my post above for "real life" example –  Nas Banov  Feb 11 '13 at 6:39

In recent Python 2.7, we have the new OrderedDict type, which remembers the order in which the items were added.

>>> d = {"third": 3, "first": 1, "fourth": 4, "second": 2}

>>> for k, v in d.items():
...     print "%s: %s" % (k, v)
...
second: 2
fourth: 4
third: 3
first: 1

>>> d
{'second': 2, 'fourth': 4, 'third': 3, 'first': 1}

To make a new ordered dictionary from the original, sorting by the values:

>>> from collections import OrderedDict
>>> d_sorted_by_value = OrderedDict(sorted(d.items(), key=lambda x: x[1]))

The OrderedDict behaves like a normal dict:

>>> for k, v in d_sorted_by_value.items():
...     print "%s: %s" % (k, v)
...
first: 1
second: 2
third: 3
fourth: 4

>>> d_sorted_by_value
OrderedDict([('first': 1), ('second': 2), ('third': 3), ('fourth': 4)])
share improve this answer
 
1 
This is not what the question is about - it is not about maintaining order of keys but about "sorting by value" –  Nas Banov  Jul 5 '10 at 7:07
5 
@Nas Banov: it is NOT sorting by the key. it is sorting in the order, we create the items. in our case, we sort by the value. unfortunately, the 3-item dict was unfortunately chosen so the order was the same, when sorted voth by value and key, so i expanded the sample dict. –  mykhal  Jul 5 '10 at 10:56

It can often be very handy to use namedtuple. For example, you have a dictionary of 'name' as keys and 'score' as values and you want to sort on 'score':

import collections
Player = collections.namedtuple('Player', 'score name')
d = {'John':5, 'Alex':10, 'Richard': 7}

sorting with lowest score first:

worst = sorted(Player(v,k) for (k,v) in d.items())

sorting with highest score first:

best = sorted([Player(v,k) for (k,v) in d.items()], reverse=True)

Now you can get the name and score of, let's say the second-best player (index=1) very Pythonically like this:

    player = best[1]
    player.name
        'Richard'
    player.score
         7
share improve this answer
 

Pretty much the same as Hank Gay's answer;

sorted([(value,key) for (key,value) in mydict.items()])
share improve this answer
 
5 
..and as with Hank Gay's answer, you don't need the square brackets. sorted() will happily take any iterable, such as a generator expression. –  John Fouhy  Mar 5 '09 at 1:45

In Python 2.7, simply do:

from collections import OrderedDict
# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by key
OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

copy-paste from : http://docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipes

Enjoy ;-)

share improve this answer
 

I had the same problem, I solved it like this:

WantedOutput = sorted(MyDict, key=lambda x : MyDict[x]) 

(people who answer: "It is not possible to sort a dict" did not read the question!! In fact "I can sort on the keys, but how can I sort based on the values?" clearly means that he wants a list of the keys sorted according to the value of their values.)

Please notice that the order is not well defined (keys with the same value will be in an arbitrary order in the output list)

share improve this answer
 

You can use the collections.Counter. Note, this will work for both numeric and non-numeric values.

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> from collections import Counter
>>> #To sort in reverse order
>>> Counter(x).most_common()
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> Counter(x).most_common()[::-1]
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
>>> #To get a dictionary sorted by values
>>> from collections import OrderedDict
>>> OrderedDict(Counter(x).most_common()[::-1])
OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])
share improve this answer
 
3 
How is this different from Ivan Sas's answer? –  Peter Mortensen  Apr 3 '14 at 17:07

UPDATE: 5 DECEMBER 2015 using Python 3.5

Whilst I found the accepted answer useful, I was also surprised that it hasn't been updated to reference OrderedDict from the standard library collections module as a viable, modern alternative - designed to solve exactly this type of problem.

from operator import itemgetter
from collections import OrderedDict

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

The official OrderedDict documentation offers a very similar example too, but using a lambda for the sort function:

# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
# OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
share improve this answer
 

You can create an "inverted index", also

from collections import defaultdict
inverse= defaultdict( list )
for k, v in originalDict.items():
    inverse[v].append( k )

Now your inverse has the values; each value has a list of applicable keys.

for k in sorted(inverse):
    print k, inverse[k]
share improve this answer
 

If values are numeric you may also use Counter from collections

from collections import Counter

x={'hello':1,'python':5, 'world':3}
c=Counter(x)
print c.most_common()


>> [('python', 5), ('world', 3), ('hello', 1)]    
share improve this answer
 

Technically, dictionaries aren't sequences, and therefore can't be sorted. You can do something like

sorted(a_dictionary.values())

assuming performance isn't a huge deal.

UPDATE: Thanks to the commenters for pointing out that I made this way too complicated in the beginning.

share improve this answer
 
from django.utils.datastructures import SortedDict

def sortedDictByKey(self,data):
    """Sorted dictionary order by key"""
    sortedDict = SortedDict()
    if data:
        if isinstance(data, dict):
            sortedKey = sorted(data.keys())
            for k in sortedKey:
                sortedDict[k] = data[k]
    return sortedDict
share improve this answer
 
1 
question was: sort by value, not by keys... I like seeing a function. You can import collections and of course use sorted(data.values()) –  Remi  Aug 30 '11 at 0:38

This is the code:

import operator
origin_list = [
    {"name": "foo", "rank": 0, "rofl": 20000},
    {"name": "Silly", "rank": 15, "rofl": 1000},
    {"name": "Baa", "rank": 300, "rofl": 20},
    {"name": "Zoo", "rank": 10, "rofl": 200},
    {"name": "Penguin", "rank": -1, "rofl": 10000}
]
print ">> Original >>"
for foo in origin_list:
    print foo

print "\n>> Rofl sort >>"
for foo in sorted(origin_list, key=operator.itemgetter("rofl")):
    print foo

print "\n>> Rank sort >>"
for foo in sorted(origin_list, key=operator.itemgetter("rank")):
    print foo

Here are the results:

Original

{'name': 'foo', 'rank': 0, 'rofl': 20000}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Baa', 'rank': 300, 'rofl': 20}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Penguin', 'rank': -1, 'rofl': 10000}

Rofl

{'name': 'Baa', 'rank': 300, 'rofl': 20}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Penguin', 'rank': -1, 'rofl': 10000}
{'name': 'foo', 'rank': 0, 'rofl': 20000}

Rank

{'name': 'Penguin', 'rank': -1, 'rofl': 10000}
{'name': 'foo', 'rank': 0, 'rofl': 20000}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Baa', 'rank': 300, 'rofl': 20}
share improve this answer
 

Why not try this approach. Let us define a dictionary called mydict with the following data:

mydict = {'carl':40,
          'alan':2,
          'bob':1,
          'danny':3}

If one wanted to sort the dictionary by keys, one could do something like:

for key in sorted(mydict.iterkeys()):
    print "%s: %s" % (key, mydict[key])

This should return the following output:

alan: 2
bob: 1
carl: 40
danny: 3

On the other hand, if one wanted to sort a dictionary by value (as is asked in the question), one could do the following:

for key, value in sorted(mydict.iteritems(), key=lambda (k,v): (v,k)):
    print "%s: %s" % (key, value)

The result of this command (sorting the dictionary by value) should return the following:

bob: 1
alan: 2
danny: 3
carl: 40
share improve this answer
 

You can use a skip dict which is a dictionary that's permanently sorted by value.

>>> data = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
>>> SkipDict(data)
{0: 0.0, 2: 1.0, 1: 2.0, 4: 3.0, 3: 4.0}

If you use keys()values() or items() then you'll iterate in sorted order by value.

It's implemented using the skip list datastructure.

share improve this answer
 

Use ValueSortedDict from dicts:

from dicts.sorteddict import ValueSortedDict
d = {1: 2, 3: 4, 4:3, 2:1, 0:0}
sorted_dict = ValueSortedDict(d)
print sorted_dict.items() 

[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
share improve this answer
 

If your values are integers, and you use Python 2.7 or newer, you can use collections.Counterinstead of dict. The most_common method will give you all items, sorted by the value.

share improve this answer
 

Iterate through a dict and sort it by its values in descending order:

$ python --version
Python 3.2.2

$ cat sort_dict_by_val_desc.py 
dictionary = dict(siis = 1, sana = 2, joka = 3, tuli = 4, aina = 5)
for word in sorted(dictionary, key=dictionary.get, reverse=True):
  print(word, dictionary[word])

$ python sort_dict_by_val_desc.py 
aina 5
tuli 4
joka 3
sana 2
siis 1
share improve this answer
 

This works in 3.1.x:

import operator
slovar_sorted=sorted(slovar.items(), key=operator.itemgetter(1), reverse=True)
print(slovar_sorted)
share improve this answer
 

You can use the sorted function of Python

sorted(iterable[, cmp[, key[, reverse]]])

Thus you can use:

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

Visit this link for more information on sorted function: https://docs.python.org/2/library/functions.html#sorted

share improve this answer
 

This returns the list of key-value pairs in the dictionary, sorted by value from highest to lowest:

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

For the dictionary sorted by key, use the following:

sorted(d.items(), reverse=True)

The return is a list of tuples because dictionaries themselves can't be sorted.

This can be both printed or sent into further computation.

share improve this answer
 
1 
There is shorter and faster way to do what you are trying: sorted(d.items(), reverse=True) –  Nas Banov  Feb 20 '14 at 20:17

For the sake of completeness, I am posting a solution using heapq. Note, this method will work for both numeric and non-numeric values

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> x_items = x.items()
>>> heapq.heapify(x_items)
>>> #To sort in reverse order
>>> heapq.nlargest(len(x_items),x_items, operator.itemgetter(1))
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> heapq.nsmallest(len(x_items),x_items, operator.itemgetter(1))
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
share improve this answer
 

I came up with this one, 

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

For Python 3.x: x.items() replacing iteritems().

>>> sorted_x
{0: 0, 1: 2, 2: 1, 3: 4, 4: 3}

Or try with collections.OrderedDict!

x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
from collections import OrderedDict

od1 = OrderedDict(sorted(x.items(), key=lambda t: t[1]))
share improve this answer
 

Here is a solution using zip on d.values() and d.keys(). A few lines down this link (on Dictionary view objects) is:

This allows the creation of (value, key) pairs using zip(): pairs = zip(d.values(), d.keys()).

So we can do the following:

d = {'key1': 874.7, 'key2': 5, 'key3': 8.1}

d_sorted = sorted(zip(d.values(), d.keys()))

print d_sorted 
# prints: [(5, 'key2'), (8.1, 'key3'), (874.7, 'key1')]
share improve this answer
 
>>> e = {1:39, 4:34, 7:110, 2:87}
>>> sortE = sorted(e.items(), key=lambda value: value[1])
>>> print(sortE)
[(4, 34), (1, 39), (2, 87), (7, 110)]

You can use a lambda function to sort things up by value and store them processed inside a variable, in this case sortE with e the original dictionary.

Best Regards. 

share improve this answer
 
months = {"January": 31, "February": 28, "March": 31, "April": 30, "May": 31,
          "June": 30, "July": 31, "August": 31, "September": 30, "October": 31,
          "November": 30, "December": 31}

def mykey(t):
    """ Customize your sorting logic using this function.  The parameter to
    this function is a tuple.  Comment/uncomment the return statements to test
    different logics.
    """
    return t[1]              # sort by number of days in the month
    #return t[1], t[0]       # sort by number of days, then by month name
    #return len(t[0])        # sort by length of month name
    #return t[0][-1]         # sort by last character of month name


# Since a dictionary can't be sorted by value, what you can do is to convert
# it into a list of tuples with tuple length 2.
# You can then do custom sorts by passing your own function to sorted().
months_as_list = sorted(months.items(), key=mykey, reverse=False)

for month in months_as_list:
    print month
share improve this answer
 

Using Python 3.2:

x = {"b":4, "a":3, "c":1}
for i in sorted(x.values()):
    print(list(x.keys())[list(x.values()).index(i)])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值