Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting a List of Elements by the First element but if Equal sort by the second

Tags:

python

I have constructed a list [[13, "b"], [10, "b"], [10, "a",], [4,"c"], [1, "d"]] which is sorted by the first value in the list of two elements. That is the part I can do. What I don't know is if two elements are the same, then I want to sort it alphabetically. The method I used to sort the first list was reversing a sorted list by the first element. This however makes [10, "b"] come before [10, "a"] but i want "a" before "b". Is there a way to write sort by first element in descending order and if a tie, sort alphabetically by the second element?

like image 288
user2587214 Avatar asked Jul 26 '13 21:07

user2587214


1 Answers

This works:

>>> li=[[13, "b"], [10, "b"], [10, "a",], [4,"c"], [1, "d"]]
>>> sorted(li,key=lambda sl: (-sl[0],sl[1]))
[[13, 'b'], [10, 'a'], [10, 'b'], [4, 'c'], [1, 'd']]

The sorted function produces a new list. You can also sort the list in place using the sort method:

>>> li=[[13, "b"], [10, "b"], [10, "a",], [4,"c"], [1, "d"]]
>>> li.sort(key=lambda sl: (-sl[0],sl[1]))
>>> li
[[13, 'b'], [10, 'a'], [10, 'b'], [4, 'c'], [1, 'd']]

You can also do a nested sort (or sort on one key, then the second key) since python uses a stable sort:

>>> from operator import itemgetter
>>> li=[[13, "b"], [10, "b"], [10, "a",], [4,"c"], [1, "d"]]
>>> li.sort(key=itemgetter(1))
>>> li
[[10, 'a'], [13, 'b'], [10, 'b'], [4, 'c'], [1, 'd']]
>>> li.sort(key=itemgetter(0),reverse=True)
>>> li
[[13, 'b'], [10, 'a'], [10, 'b'], [4, 'c'], [1, 'd']]

Since there is no need for a lambda in a one element sort, I used the faster operator.itemgetter vs a lambda. Whether two faster sorts are faster than one, I don't know... You can also use a lambda for this method.

There is a great sort tutorial that shows many of these idioms.

like image 180
dawg Avatar answered Nov 03 '22 23:11

dawg