By Gern Blanston


2009-03-05 00:49:05 8 Comments

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.

30 comments

@Devin Jeanpierre 2009-03-05 00:59:34

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 [1] 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 = OrderedDict(sorted_x)

@Gregg Lind 2009-03-14 17:55:50

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

@saidimu apale 2010-05-03 05:24:35

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

@rmh 2010-07-05 02:59:42

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

@Keyo 2011-02-15 15:05:11

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

@Devin Jeanpierre 2011-02-21 13:06:29

@Keyo yes; 3.x doesn't have the iteritems() method anymore. However, you can still use the operator module (if you want).

@monkut 2011-04-24 06:31:11

OrderedDict added to collections in 2.7. Sorting example shown at: docs.python.org/library/…

@riot_starter 2013-05-17 23:40:27

for i in range(1, 11): print u"{0} {1}".format(sorted_tags[i], sorted_tags[i][1])

@Logan Yang 2013-09-29 10:32:02

Your x here is not a list of tuples, for x = [(1, 2), (3, 4), (4, 3), (2,1), (0,0)], there will be no iteritems() in sorted().

@martineau 2013-10-15 14:17:56

@Logan: What are you talking about? x is a dictionary and the question is about sorting one based on its values.

@Dejell 2014-01-07 20:56:01

@Keyo this will return only the key - hoe do you return also the value?

@Devin Jeanpierre 2014-01-19 01:11:49

@Dejel no, in Python 3.x sorted(d.items(), key=...) will return a list of (key, value) tuples.

@Phil Braun 2014-05-16 14:38:58

To get the reverse you can also use call the function with reverse = True as a parameter.

@Devin Jeanpierre 2015-01-15 09:57:22

I'm not sure I like the edit (and it's my answer!). To sort on keys, I would usually do sorted(x.items()). This works unless the dict has uncomparable values.

@Nitin 2016-05-13 22:37:30

sorted_x = sorted(x.items(), key=operator.itemgetter(1), reverse=True) looks better than first sorting them in ascending and then flipping the list.

@Dilettant 2016-09-10 09:35:53

... and starting with Python 3.6 the "PEP 468 "Preserving the order of **kwargs in a function" is now implemented! Based on INADA Naoki's implementation of the "compact dict" this would help here in case one inserts the items in value order. Then one can retrieve in that same order with iteration over the dict (with the built-in dict :-) ...)

@Imanez 2016-10-24 08:32:43

When I have dict with different keys (upper case and Lower case ), List output with uppercase string first and then lowercase

@Hitesh Garg 2016-11-24 09:10:51

@codervince 2017-03-12 03:40:31

what if you have Nones in the values? TypeError: '<' not supported between instances of 'NoneType' and 'float' In which case, for Nones to appear at end: s = sorted(d.items(), key=lambda value: float('inf') if value[1] is None else value[1])

@Devin Jeanpierre 2017-03-27 18:21:39

@codervince Yeah, that's exactly what I'd do in that situation.

@JeeYem 2017-05-16 23:01:26

Module natsort can be used for natural sorting, if strings that are to be sorted are alphanumerics. Example: For input: ['ch1', 'ch2', 'ch12'], sorted output is ['ch1', 'ch12', 'ch2'], whereas natsort.natsorted output is ['ch1', 'ch2', 'ch12'].

@gerrit 2018-12-19 17:11:21

This answer is out of date. Dictionaries are sorted in Python 3.7.

@Willwsharp 2019-04-12 19:07:48

what do you mean we can only get a "representation of a dictionary that is sorted"?

@Wira Bhakti 2019-02-26 04:12:26

Beside using builtin module etc, i try solve it manually..... first i made a function whose job is to returning minimal value each items of the dict :

def returnminDict(_dct):
    dict_items = _dct.items()
    list_items = list(dict_items)
    init_items = list_items[0]
    for i in range(len(list_items)):
        if list_items[i][1] > init_items[1]:
           continue
        else:
           init_items = list_items[i]
    return init_items

Second, now we have a function which return item that has minimal value, then i make a new dict then loop over the dict :

def SelectDictSort(_dct):
    new_dict = {}
    while _dct:
        mindict = returnminDict(_dct)
        new_dict.update(dict((mindict,)))
        _dct.pop(mindict[0])
    return new_dict

i try this SelectDictSort({2: 5, 5: 1, 4: 3, 1: 1, 0: 1, 9: 2, 8: 2}) will return :

{0: 1, 1: 1, 5: 1, 8: 2, 9: 2, 4: 3, 2: 5}

Hmmm... i dont know which is correct but this what i have tried....

(updated code from retrun new_dct to return new_dict)

@user26294 2009-03-05 01:06:04

Pretty much the same as Hank Gay's answer:

sorted([(value,key) for (key,value) in mydict.items()])

Or optimized slightly as suggested by John Fouhy:

sorted((value,key) for (key,value) in mydict.items())

@John Fouhy 2009-03-05 01:45:48

..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.

@saidimu apale 2010-05-03 05:22:24

You may still need to swap the (value,key) tuple elements to end up with the (key, value). Another list comprehension is then needed. [(key, value) for (value, key) in sorted_list_of_tuples]

@Jean-François Fabre 2017-12-07 21:21:54

no, it's better to leave square brackets, because sorted will have to rebuild the list anyway, and rebuilding from gencomp will be faster. Good for codegolfing, bad for speed. Keep the ugly ([]) version.

@Bram Vanroy 2018-03-02 16:48:07

As pointed out by Dilettant, Python 3.6 will now keep the order! I thought I'd share a function I wrote that eases the sorting of an iterable (tuple, list, dict). In the latter case, you can sort either on keys or values, and it can take numeric comparison into account. Only for >= 3.6!

When you try using sorted on an iterable that holds e.g. strings as well as ints, sorted() will fail. Of course you can force string comparison with str(). However, in some cases you want to do actual numeric comparison where 12 is smaller than 20 (which is not the case in string comparison). So I came up with the following. When you want explicit numeric comparison you can use the flag num_as_num which will try to do explicit numeric sorting by trying to convert all values to floats. If that succeeds, it will do numeric sorting, otherwise it'll resort to string comparison.

Comments for improvement or push requests welcome.

def sort_iterable(iterable, sort_on=None, reverse=False, num_as_num=False):
    def _sort(i):
      # sort by 0 = keys, 1 values, None for lists and tuples
      try:
        if num_as_num:
          if i is None:
            _sorted = sorted(iterable, key=lambda v: float(v), reverse=reverse)
          else:
            _sorted = dict(sorted(iterable.items(), key=lambda v: float(v[i]), reverse=reverse))
        else:
          raise TypeError
      except (TypeError, ValueError):
        if i is None:
          _sorted = sorted(iterable, key=lambda v: str(v), reverse=reverse)
        else:
          _sorted = dict(sorted(iterable.items(), key=lambda v: str(v[i]), reverse=reverse))

      return _sorted

    if isinstance(iterable, list):
      sorted_list = _sort(None)
      return sorted_list
    elif isinstance(iterable, tuple):
      sorted_list = tuple(_sort(None))
      return sorted_list
    elif isinstance(iterable, dict):
      if sort_on == 'keys':
        sorted_dict = _sort(0)
        return sorted_dict
      elif sort_on == 'values':
        sorted_dict = _sort(1)
        return sorted_dict
      elif sort_on is not None:
        raise ValueError(f"Unexpected value {sort_on} for sort_on. When sorting a dict, use key or values")
    else:
      raise TypeError(f"Unexpected type {type(iterable)} for iterable. Expected a list, tuple, or dict")

@Maxime Chéramy 2018-09-15 13:37:17

Starting from Python 3.6, dict objects are now ordered by insertion order. It's officially in the specs of Python 3.7.

>>> words = {"python": 2, "blah": 4, "alice": 3}
>>> dict(sorted(words.items(), key=lambda x: x[1]))
{'python': 2, 'alice': 3, 'blah': 4}

Before that, you had to use OrderedDict.

Python 3.7 documentation says:

Changed in version 3.7: Dictionary order is guaranteed to be insertion order. This behavior was implementation detail of CPython from 3.6.

@Maxime Chéramy 2018-10-10 15:43:50

Downvoter, please explain...

@fuyas 2018-10-24 09:17:19

Not the downvoter but a link to the documentation to would be nice, as this sounds like quite a change to how dictionaries have been seen so far...

@Maxime Chéramy 2018-10-24 14:19:45

Thanks @fuyas I've added a link to the documentation with a quote saying that the order is now guaranteed.

@vizyourdata 2018-11-19 20:10:53

works great! dict(sorted(words.items(), key=lambda x: x[1], reverse=True)) for DESC

@iNet 2018-07-14 13:22:16

Thomas Cokelaer explains this in a very elegant way. I like to mention a quick note of his article.

Let us consider the following dictionary.

d = {"Pierre": 42, "Anne": 33, "Zoe": 24}

To sort based on the values, some following approaches are presented.

sorted function and operator module

import operator
sorted_d = sorted(d.items(), key=operator.itemgetter(1))


sorted function and lambda function

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


sorted function and return an ordered dictionary

In the previous methods, the returned objects are the list of tuples. So we do not have a dictionary anymore. We can use an OrderedDict if we prefer.

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


sorted function and list comprehension

sorted_d = sorted((value, key) for (key,value) in d.items())

However, He also made a quick benchmark of the above procedure.

@mcgag 2018-05-27 17:45:24

Just learned relevant skill from Python for Everybody.

You may use a temporary list to help you to sort the dictionary:

#Assume dictionary to be:
d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0}

# create a temporary list
tmp = []

# iterate through the dictionary and append each tuple into the temporary list 
for key, value in d.items():
    tmptuple = (value, key)
    tmp.append(tmptuple)

# sort the list in ascending order
tmp = sorted(tmp)

print (tmp)

If you want to sort the list in descending order, simply change the original sorting line to:

tmp = sorted(tmp, reverse=True)

Using list comprehension, the one liner would be:

#Assuming the dictionary looks like
d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0}
#One liner for sorting in ascending order
print (sorted([(v, k) for k, v in d.items()]))
#One liner for sorting in descending order
print (sorted([(v, k) for k, v in d.items()], reverse=True))

Sample Output:

#Asending order
[(1.0, 'orange'), (500.1, 'apple'), (789.0, 'pineapple'), (1500.2, 'banana')]
#Descending order
[(1500.2, 'banana'), (789.0, 'pineapple'), (500.1, 'apple'), (1.0, 'orange')]

@Nathaniel Payne 2014-04-07 04:46:44

Try the following 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

@Andomar 2017-07-07 19:08:07

Awesome! for key, value in sorted(mydict.iteritems(), key=lambda (k,v): v["score"]): allows you to sort by a subkey

@xiyurui 2017-05-24 03:19:04

This method will not use lambda and works well on Python 3.6:

 # sort dictionary by value
d = {'a1': 'fsdfds', 'g5': 'aa3432ff', 'ca':'zz23432'}
def getkeybyvalue(d,i):
    for k, v in d.items():
        if v == i:
            return (k)

sortvaluelist = sorted(d.values())

# In >> Python 3.6+ << the INSERTION-ORDER of a dict is preserved. That is,
# when creating a NEW dictionary and filling it 'in sorted order',
# that order will be maintained.
sortresult ={}
for i1 in sortvaluelist:   
    key = getkeybyvalue(d,i1)
    sortresult[key] = i1
print ('=====sort by value=====')
print (sortresult)
print ('=======================')

@HDJEMAI 2017-05-24 03:37:42

From review queue: May I request you to please add some context around your source-code. Code-only answers are difficult to understand. It will help the asker and future readers both if you can add more information in your post.

@Dilettant 2016-09-10 10:05:36

As of Python 3.6 the built-in dict will be ordered

Good news, so the OP's original use case of mapping pairs retrieved from a database with unique string ids as keys and numeric values as values into a built-in Python v3.6+ dict, should now respect the insert order.

If say the resulting two column table expressions from a database query like:

SELECT a_key, a_value FROM a_table ORDER BY a_value;

would be stored in two Python tuples, k_seq and v_seq (aligned by numerical index and with the same length of course), then:

k_seq = ('foo', 'bar', 'baz')
v_seq = (0, 1, 42)
ordered_map = dict(zip(k_seq, v_seq))

Allow to output later as:

for k, v in ordered_map.items():
    print(k, v)

yielding in this case (for the new Python 3.6+ built-in dict!):

foo 0
bar 1
baz 42

in the same ordering per value of v.

Where in the Python 3.5 install on my machine it currently yields:

bar 1
foo 0
baz 42

Details:

As proposed in 2012 by Raymond Hettinger (cf. mail on python-dev with subject "More compact dictionaries with faster iteration") and now (in 2016) announced in a mail by Victor Stinner to python-dev with subject "Python 3.6 dict becomes compact and gets a private version; and keywords become ordered" due to the fix/implementation of issue 27350 "Compact and ordered dict" in Python 3.6 we will now be able, to use a built-in dict to maintain insert order!!

Hopefully this will lead to a thin layer OrderedDict implementation as a first step. As @JimFasarakis-Hilliard indicated, some see use cases for the OrderedDict type also in the future. I think the Python community at large will carefully inspect, if this will stand the test of time, and what the next steps will be.

Time to rethink our coding habits to not miss the possibilities opened by stable ordering of:

  • Keyword arguments and
  • (intermediate) dict storage

The first because it eases dispatch in the implementation of functions and methods in some cases.

The second as it encourages to more easily use dicts as intermediate storage in processing pipelines.

Raymond Hettinger kindly provided documentation explaining "The Tech Behind Python 3.6 Dictionaries" - from his San Francisco Python Meetup Group presentation 2016-DEC-08.

And maybe quite some Stack Overflow high decorated question and answer pages will receive variants of this information and many high quality answers will require a per version update too.

Caveat Emptor (but also see below update 2017-12-15):

As @ajcr rightfully notes: "The order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon." (from the whatsnew36) not nit picking, but the citation was cut a bit pessimistic ;-). It continues as " (this may change in the future, but it is desired to have this new dict implementation in the language for a few releases before changing the language spec to mandate order-preserving semantics for all current and future Python implementations; this also helps preserve backwards-compatibility with older versions of the language where random iteration order is still in effect, e.g. Python 3.5)."

So as in some human languages (e.g. German), usage shapes the language, and the will now has been declared ... in whatsnew36.

Update 2017-12-15:

In a mail to the python-dev list, Guido van Rossum declared:

Make it so. "Dict keeps insertion order" is the ruling. Thanks!

So, the version 3.6 CPython side-effect of dict insertion ordering is now becoming part of the language spec (and not anymore only an implementation detail). That mail thread also surfaced some distinguishing design goals for collections.OrderedDict as reminded by Raymond Hettinger during discussion.

@Alex Riley 2016-09-10 20:15:16

The warning on the 'whatsnew' page you've linked to should be emphasised: the order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon. Nobody should be assuming that the dict type will respect insertion order in their code. This is not part of the language's definition and the implementation could change in any future release. Continue using OrderedDict to guarantee order.

@Dilettant 2016-09-10 20:22:56

@ajcr thanks for the caveat, very appreciated - as smileys and maybe's were weaved into my response,these should indicated, the change is massive but of course, only available for CPython (reference implementation) and PyPy. For something completely different ... I rarely talk to non-implementation details when coding man-machine instructions. If it would only have been Jython ;-) ... I might not have had the courage to write it.

@Jim Fasarakis Hilliard 2016-12-10 13:33:02

OrderedDict definitely won't be dropped; instead, it will become a thin wrapper around the current dict implementation (so you might add that it will become more compact, too). Adding that snippet with the ImportError isn't quite the best idea due to it misleading readers that OrderedDict has no use.

@Dilettant 2016-12-10 13:58:51

@JimFasarakis-Hilliard thank you for the feedback. "Quite best ideas" made me smile - future is often hard to predict. But I like your suggestion will check the sources, try it and then update the answer accordingly. Thanks again.

@Bram Vanroy 2018-03-02 16:49:04

In a response to this answer, and structured dicts, I posted a new answer. Feedback welcome!

@gerrit 2018-12-19 17:12:48

@AlexRiley This caveat is no longer accurate. Python3.7 guarantees ordered dictionaries.

@Alex Riley 2019-01-02 21:19:59

@gerrit: sure, my comment and the subsequent exchange is no longer relevant given the change in the language. Is it best to delete the comment or leave it around for posterity?

@gerrit 2019-01-02 22:23:43

@AlexRiley I think we can leave it, and then readers who read on can read my replying comment

@Dilettant 2019-01-02 22:56:55

The future is a more or less unknown place ... these long comment threads are rarely visible without digging. I upvoted @gerrit 's comment, so at least both comments are visible to the casual visitor - thanks for sustaining the vision ;-) I would not delete comments (regardless of my like or dislike).

@jimifiki 2010-11-18 14:19:57

I had the same problem, and 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).

@Dejell 2014-01-07 20:54:43

You are missing the value from the result

@Ron Klein 2016-09-21 08:00:26

Note that you're both iterating the dictionary and fetching values by their key, so performance wise this is not an optimal solution.

@Max 2019-01-12 03:19:58

@Dejell: as the contributor says, he interprets the question as "can I get the list of keys sorted according to the values". We don't need the values in the result, we have them in the dictionary.

@Hank Gay 2009-03-05 00:56:12

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.

@Devin Jeanpierre 2009-03-05 01:14:01

The list comprehension is no longer needed. You can simply pass in sorted(a_dictionary.values()). Even faster, if we want more would be to do foo = a_dictionary.values(); foo.sort() . I don't think speed is that much of an issue, though. Getting rid of the listcomp would simply eliminate redundancy.

@guerreroz 2016-01-25 14:54:43

Given dictionary

e = {1:39, 4:34, 7:110, 2:87}

Sorting

sred = sorted(e.items(), key=lambda value: value[1])

Result

[(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 sred with e the original dictionary.

Hope that helps!

@Vishwanath Rawat 2017-05-25 18:13:11

You can also use custom function that can be passed to key.

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

One more way to do is to use labmda function

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

@Remi 2011-08-30 00:30:15

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

@rowana 2017-02-07 20:31:44

How could I convert it back to a dictionary?

@Remi 2017-02-23 12:31:13

as_list=[Player(v,k) for (k,v) in d.items()] as_dict=dict((p.name,p.score) for p in as_list)

@Nas Banov 2010-07-05 08:01:16

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 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.

@smci 2011-12-09 21:18:26

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

@rjurney 2013-04-12 23:13:59

You will first need to: import collections # to use defaultdict

@Nas Banov 2014-02-27 19:01:05

@Zags you are doing different thing - constructing list of tuples (key,val) sorted by key. Can be done simpler: sorted(d.items(), reverse=True)

@Zags 2014-02-27 20:17:48

As posted in an answer below, this is a form that can be both printed and used in further computation: sorted(d.items(), reverse=True)

@bli 2014-08-13 15:58:40

@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)

@Izkata 2014-08-19 20:21:15

@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

@Eevee 2017-06-25 20:47:44

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

@Nas Banov 2017-06-27 17:33:30

@Eevee, i see sarcasm is alive and well in the future. But do they know what "code golf" is (as mentioned in the motivating example)?

@Eevee 2017-06-27 22:00:12

i think you might be interpreting hostility where there be none; i say i'm coming from the future because i know this is an old answer and i'm genuinely not sure Counter even existed seven years ago

@Nas Banov 2017-06-28 21:56:09

@Eevee - there is that, the risk of being misunderstood in non-f2f short comments. Amuzing tidbit: collections.Counter was added in 2.7, which was released almost exactly 7 years ago! (I did not know about it then - plus i would have avoided it in code-golf for the purpose of brevity, which is the game's sole obsession)

@Michael H. 2018-04-12 10:02:37

You can improve your first block of code where you count occurrences of words and store them in a dict. Use this: d = {}; for w in text.split():; d[w] = d.get(w, 0) + 1

@smci 2019-03-13 06:06:33

@Bokje: you only mean 'improve' in the code-golf sense that that's shorter, (but more cryptic), right? The code-golf aspect is obfuscating simple answers to this question...

@PedroMorgan 2011-03-08 02:06:25

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}

@arcseldon 2015-12-05 09:46:06

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)])

@Zags 2014-02-12 20:10:46

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.

@Nas Banov 2014-02-20 20:17:12

There is shorter and faster way to do what you are trying: sorted(d.items(), reverse=True)

@skillman 2015-07-29 01:08:13

I've found that the following function performs well compared to other solutions posted, even on large dictionaries.

vsort = lambda d: sorted(d.iteritems(), key=lambda (k, v): v)

Example:

data = {}
for i in range(10):
    data[i] = i if i % 2  else -i

print 'Original'
for k, v in data.items():
    print "k: %s v: %s" % (k, v)
print ''

print 'Value-sorted'
for k, v in vsort(data):
    print "k: %s v: %s" % (k, v)
print ''

Output:

Original
k: 0 v: 0
k: 1 v: 1
k: 2 v: -2
k: 3 v: 3
k: 4 v: -4
k: 5 v: 5
k: 6 v: -6
k: 7 v: 7
k: 8 v: -8
k: 9 v: 9

Value-sorted
k: 8 v: -8
k: 6 v: -6
k: 4 v: -4
k: 2 v: -2
k: 0 v: 0
k: 1 v: 1
k: 3 v: 3
k: 5 v: 5
k: 7 v: 7
k: 9 v: 9

Sample timing code:

import numpy as np
from time import time
import operator
np.random.seed(0)

N = int(1e6)
x = {i: np.random.random() for i in xrange(N)}

t0 = -time()
sorted_0 = sorted(x.items(), key=operator.itemgetter(1))
t0 += time()

t1 = -time()
sorted_1 = vsort(x)
t1 += time()

print 'operator-sort: %f vsort: %f' % (t0, t1)
print sorted_0[:3]
print sorted_1[:3]

Output:

operator-sort: 2.041510 vsort: 1.692324
[(661553, 7.071203171893359e-07), (529124, 1.333679640169727e-06), (263972, 2.9504162779581122e-06)]
[(661553, 7.071203171893359e-07), (529124, 1.333679640169727e-06), (263972, 2.9504162779581122e-06)]

@ytpillai 2015-07-31 08:09:24

Please understand that dictionaries do not keep their order. In order to directly do this, you need to make a generator function

@ytpillai 2015-07-31 08:08:49

Of course, remember, you need to use OrderedDict because regular Python dictionaries don't keep the original order.

from collections import OrderedDict
a = OrderedDict(sorted(originalDict.items(), key = lambda x: x[1]))

If you do not have Python 2.7 or higher, the best you can do is iterate over the values in a generator function. (There is an OrderedDict for 2.4 and 2.6 here, but

a) I don't know about how well it works 

and

b) You have to download and install it of course. If you do not have administrative access, then I'm afraid the option's out.)

def gen(originalDict):
    for x,y in sorted(zip(originalDict.keys(), originalDict.values()), key = lambda z: z[1]):
        yield (x, y)
    #Yields as a tuple with (key, value). You can iterate with conditional clauses to get what you want. 

for bleh, meh in gen(myDict):
    if bleh == "foo":
        print(myDict[bleh])

You can also print out every value

for bleh, meh in gen(myDict):
    print(bleh,meh)

Please remember to remove the parentheses after print if not using Python 3.0 or above

@gerrit 2018-12-19 17:13:36

regular Python dictionaries don't keep the original order — as of Python 3.7, they do.

@Scott 2015-06-20 01:44:58

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')]

@kkk 2014-11-21 15:04:09

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

@malthe 2014-09-25 22:56:55

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.

@Roberto Bonvallet 2009-03-05 01:05:22

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))

@Remi 2011-08-30 23:42:37

+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.

@SabreWolfy 2012-06-18 10:04:04

What order are keys with the same value placed in? I sorted the list by keys first, then by values, but the order of the keys with the same value does not remain.

@Nas Banov 2013-02-11 06:39:14

@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

@Eamonn Kenny 2014-03-03 14:58:30

Because of requirements to retain backward compatability with older versions of Python I think the OrderedDict solution is very unwise. You want something that works with Python 2.7 and older versions.

But the collections solution mentioned in another answer is absolutely superb, because you retrain a connection between the key and value which in the case of dictionaries is extremely important.

I don't agree with the number one choice presented in another answer, because it throws away the keys.

I used the solution mentioned above (code shown below) and retained access to both keys and values and in my case the ordering was on the values, but the importance was the ordering of the keys after ordering the values.

from collections import Counter

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


>> [('python', 5), ('world', 3), ('hello', 1)]

@octoback 2013-05-08 08:17:55

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]))

@agf 2013-07-27 16:32:08

if you're going to do it this way, at leat take advantage of tuple unpacking in the dictionary comprehension: {key: value for key, value in ...}

@Abhijit 2013-03-09 12:30:22

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)])

@Peter Mortensen 2014-04-03 17:07:08

How is this different from Ivan Sas's answer?

@raton 2012-11-03 11:07:21

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)])

@mykhal 2010-07-05 02:50:41

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)])

@Nas Banov 2010-07-05 07:07:53

This is not what the question is about - it is not about maintaining order of keys but about "sorting by value"

@mykhal 2010-07-05 10:56:20

@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.

@JZAU 2013-11-08 05:12:55

sorted(d.items(), key=lambda x: x[1]) Can you explain what the x means, why it can take x[1] to lambda? Why does it can't be x[0]? Thank you very much!

@CadentOrange 2013-11-19 09:06:55

@jie d.items() returns a list of key/value pairs from the dictionary and x is an element of this tuple. x[0] will be key and x[1] will be the value. As we intend to sort on the value, we pass x[1] to the lambda.

@Boern 2017-08-31 14:28:50

may be a stupid question: x: x[1] - what does the 1 access? The value itself? What is 0 then? The key?

@BallpointBen 2018-04-10 14:29:55

@Boern d.items() returns a list-like container of (key, value) tuples. [0] accesses the first element of the tuple -- the key -- and [1] accesses the second element -- the value.

Related Questions

Sponsored Content

40 Answered Questions

[SOLVED] Sort array of objects by string property value

21 Answered Questions

[SOLVED] Check if a given key already exists in a dictionary

  • 2009-10-21 19:05:09
  • Mohan Gulati
  • 2791417 View
  • 2642 Score
  • 21 Answer
  • Tags:   python dictionary

44 Answered Questions

[SOLVED] How to merge two dictionaries in a single expression?

15 Answered Questions

[SOLVED] Add new keys to a dictionary?

  • 2009-06-21 22:07:39
  • lfaraone
  • 2885789 View
  • 2216 Score
  • 15 Answer
  • Tags:   python dictionary

13 Answered Questions

[SOLVED] Iterating over dictionaries using 'for' loops

19 Answered Questions

18 Answered Questions

[SOLVED] How do you sort a dictionary by value?

49 Answered Questions

[SOLVED] Sort a Map<Key, Value> by values

26 Answered Questions

[SOLVED] What is the best way to iterate over a dictionary?

  • 2008-09-26 18:20:06
  • Jake Stewart
  • 1334306 View
  • 2229 Score
  • 26 Answer
  • Tags:   c# dictionary loops

36 Answered Questions

[SOLVED] How to pair socks from a pile efficiently?

Sponsored Content