53

I can sort by key or value, but I need it sorted by value, then key, in one line. To explain this better I can show you my problem:

dict = {'apple': 2, 'banana': 3, 'almond':2 , 'beetroot': 3, 'peach': 4} 

I want my output to be sorted descending by their value and then ascending (A-Z) by their key (alphabetically). Resulting in such a list:

With the output of: ['peach', 'banana', 'beetroot', 'almond', 'apple']

The only way I know how to do it so far is:

[v[0] for v in sorted(dict.items(), key=lambda(k,v): (v,k))] 

With the output of: ['almond', 'apple', 'banana', 'beetroot', 'peach']

So it has sorted the values in ascending order and the keys alphabetically in ascending order (A-Z). So if I reverse this:

[v[0] for v in sorted(dict.items(), key=lambda(k,v): (v,k), reverse=True)] 

With the output of: ['peach', 'beetroot', 'banana', 'apple', 'almond']

It has sorted the values in descending order and the keys alphabetically in descending order (Z-A).

Is there a way I can sort the values in descending order and the keys in ascending order (i.e. A-Z) and get the output I showed above?

0

3 Answers 3

60

You need to take advantage of the fact that the values are numbers.

>>> [v[0] for v in sorted(d.iteritems(), key=lambda(k, v): (-v, k))] ['peach', 'banana', 'beetroot', 'almond', 'apple'] 
Sign up to request clarification or add additional context in comments.

5 Comments

Just a reminder that Python 3 removed tuple parameter unpacking, so the line above should now be written as [v[0] for v in sorted(d.items(), key=lambda kv: (-kv[1], kv[0]))]. See PEP 3113 python.org/dev/peps/pep-3113
The key function could also be written as operator.itemgetter(1, 0) if you don't have to reverse the ordering of one of key/value.
What does key=lambda(k, v): (-v, k)) mean? I understand lambda is an anonymous function but the fact that it doesnt have a return statement is confusing.
@NickKiermaier: The expression is what is returned.
@GuiAmbros, lambda kv: (-kv[1]... is awful. No other syntax support in 3?
6

To sort by descending value is, for negatable quantities, to sort by ascending negative-of-value.

[v[0] for v in sorted(dict.items(), key=lambda(k,v): (-v,k))] 

Comments

2
>>> d = {'apple':2, 'banana':3, 'almond':2, 'beetroot':3, 'peach':4} >>> [k for k, v in sorted(d.iteritems(), key=lambda(k, v): (-v, k))] ['peach', 'banana', 'beetroot', 'almond', 'apple'] 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.