29

I've got a dictionary like:

{ 'a': 6, 'b': 1, 'c': 2 }

I'd like to iterate over it by value, not by key. In other words:

(b, 1)
(c, 2)
(a, 6)

What's the most straightforward way?

mike
  • 46,876
  • 44
  • 102
  • 112
  • 1
    duplicate http://stackoverflow.com/questions/613183/sort-a-dictionary-in-python-by-the-value – Devin Jeanpierre Mar 23 '09 at 18:00
  • 6
    Not a dupe. The other one wants to sort a dictionary, which is impossible. I want to iterate over a dictionary in a sorted order. – mike Mar 23 '09 at 18:04
  • and the code is exactly the same. – SilentGhost Mar 23 '09 at 18:05
  • Since you can't sort a dictionary, the code **must** be the same. Duplicate. – S.Lott Mar 23 '09 at 18:13
  • 1
    The answers are the same, but the questions are different. I found the other one before I posted this, read the question, and said, "No, this isn't what I'm asking". That's why I posted this. – mike Mar 23 '09 at 18:35
  • @Mike: and what difference do you see between that question and yours? – SilentGhost Mar 23 '09 at 18:38
  • 8
    That question is asking how to do something impossible: sort a dictionary. Dictionaries can't be sorted. I'm asking how to do something possible: iterate over a dictionary in sorted order. Dictionaries *can* be iterated over in sorted order. – mike Apr 02 '09 at 18:21

4 Answers4

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

for these of you that hate lambda :-)

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

However operator version requires CPython 2.5+

vartec
  • 131,205
  • 36
  • 218
  • 244
7

For non-Python 3 programs, you'll want to use iteritems to get the performance boost of generators, which yield values one at a time instead of returning all of them at once.

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

For even larger dictionaries, we can go a step further and have the key function be in C instead of Python as it is right now with the lambda.

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

Hooray!

hao
  • 10,138
  • 1
  • 35
  • 50
  • Oooh. Nice with the operator.itemgetter. Sweet. – Barry Wark Mar 23 '09 at 19:34
  • Though I haven't tested, I'm sceptical about the claim that `sorted` performs better on a consumable iterator than a list. I'd guess that the very first thing `sorted` does is read that iterator into a list anyway; it's very unclear whether there's a performance gain to be had, here. – Mark Amery May 26 '16 at 10:09
5

It can often be very handy to use namedtuple. For example, you have a dictionary of name and score 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)

The order of 'key' and 'value' in the listed tuples is (value, key), but 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
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Remi
  • 20,619
  • 8
  • 57
  • 41
3

The items method gives you a list of (key,value) tuples, which can be sorted using sorted and a custom sort key:

Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13) 

>>> a={ 'a': 6, 'b': 1, 'c': 2 }
>>> sorted(a.items(), key=lambda (key,value): value)
[('b', 1), ('c', 2), ('a', 6)]

In Python 3, the lambda expression will have to be changed to lambda x: x[1].

Barry Wark
  • 107,306
  • 24
  • 181
  • 206