Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sorting values of python dict using sorted builtin function

Tags:

python

sorting

I need to get a sorted representation of a dict ,sorted in the descending order of values (largest value in dict to be shown first).

sample:

mydict={u'jon':30,u'den':26,u'rob':42,u'jaime':31}

I need to show them like

rob=42
jaime=31
jon=30
den=28

I tried this

from operator import itemgetter
sortedvalues=sorted(mydict,key=itemgetter(1))

When I print the list I get

[u'jaime', u'den', u'rob', u'jon']

This list is unordered! Am I missing something about the usage of sorted builtin ? or am I using the itemgetter incorrectly?

like image 995
Damon Julian Avatar asked Mar 24 '12 04:03

Damon Julian


People also ask

How do you sort a dictionary by sorted?

First, we use the sorted() function to order the values of the dictionary. We then loop through the sorted values, finding the keys for each value. We add these keys-value pairs in the sorted order into a new dictionary. Note: Sorting does not allow you to re-order the dictionary in-place.

Can the sorted function work on a dictionary?

In contrast to the sort() method which only works on lists, the sorted() function can work on any iterable, such as lists, tuples, dictionaries, and others.


3 Answers

This is an interesting problem because you didn't cause an error like you would have if the keys were of another non-indexable type (say integers), and this is due to a subtle series of things:

  1. sorted(mydict, ...) tries to iterate a dictionary using the equivalent of iter(mydict) which will call mydict.__iter__()
  2. Iterating a dictionary yields its keys, in effect iter(mydict) is the same as mydict.iterkeys().
  3. Your keys were strings, and since strings are indexable, itemgetter(1) will work on a string value, getting the second character in the string.

The code you had would've failed with an IndexError if any strings had a 1-char length as well, you just lucked by. (or didn't, depending on how you look at it, since getting the IndexError would've made you aware of the problem sooner.)

What you want to do if you only want the values is:

sorted(mydict.values(), reverse=True)

And if you want the keys as well in pairs, you want

sorted(mydict.iteritems(), key=itemgetter(1), reverse=True)
like image 95
Crast Avatar answered Nov 14 '22 21:11

Crast


They're sorted by the second letter in the name; iterating over a dict yields its keys.

sorteditems = sorted(mydict.iteritems(), key=itemgetter(1))
like image 44
Ignacio Vazquez-Abrams Avatar answered Nov 14 '22 22:11

Ignacio Vazquez-Abrams


Iterating over a dictionary (which is what the sorted function does) will give you only it's keys:

>>> sorted(mydict)
[u'den', u'jaime', u'jon', u'rob']

Instead you want to sort both the keys and values - to do this, you would use mydict.items() (or mydict.iteritems(), which is more efficient with large dicts):

>>> sorted(mydict.items())
[(u'den', 26), (u'jaime', 31), (u'jon', 30), (u'rob', 42)]

Then your code would work as expected:

>>> from operator import itemgetter
>>> sorted(mydict.items(), key = itemgetter(1))
[(u'den', 26), (u'jon', 30), (u'jaime', 31), (u'rob', 42)]

You may also want to sort with the dict's key as the secondary sort value, in case multiple keys have the same value:

>>> mydict={u'a': 1, 'z': 1, 'd': 1}
>>> sorted(mydict.items(), key = itemgetter(1))
[(u'a', 1), ('z', 1), ('d', 1)]
>>> sorted(mydict.items(), key = itemgetter(1, 0))
[(u'a', 1), ('d', 1), ('z', 1)]
like image 32
dbr Avatar answered Nov 14 '22 21:11

dbr