37

I have following type of list

lst = [
    [1, 0.23],
    [2, 0.39],
    [4, 0.31],
    [5, 0.27],
]

I want to sort this in descending order of the second column. I tried built-in sorted() function in python, but it gives me 'TypeError' : 'float' object is unsubscriptable.

martineau
  • 119,623
  • 25
  • 170
  • 301
  • 3
    I'm sorry, but that's not a list. That is a sequence of numbers with newlines, but not any Python structure. Please post the actual code that failed for you, and the representation of the list. – Martijn Pieters Sep 01 '13 at 22:46
  • 2
    Now we have a sequence of python lists; is there an outer list? – Martijn Pieters Sep 01 '13 at 22:47
  • 12
    Clearly not off-topic, since it's the #1 Google search result for sorting a 2D list in Python, and the best answer has 15 up-votes. – JeffThompson Jun 26 '17 at 15:53
  • 1
    Agreed. If StackOverflow explains why this is off-topic, we could improve it. It is a typical question to ask how to do a non-trivial task in Python, and the task has multiple approaches as shown below. – yellowjacket05 Sep 07 '20 at 16:30

2 Answers2

67

You can use a lambda:

>>> li=[[1, 0.23],
... [2, 0.39],
... [4, 0.31],
... [5, 0.27]]
>>> sorted(li,key=lambda l:l[1], reverse=True)
[[2, 0.39], [4, 0.31], [5, 0.27], [1, 0.23]]

Or the other way:

>>> sorted(li,key=lambda l:l[1])
[[1, 0.23], [5, 0.27], [4, 0.31], [2, 0.39]]
dawg
  • 98,345
  • 23
  • 131
  • 206
  • Thank you for the answer, works a treat, but mind explaining what 'l:l[1]' do? – Ricardo Sanchez Dec 13 '20 at 08:48
  • 4
    A lambda is a small anonymous function in Python. The `l` is the argument to the lambda separated by the body of the function by `:`. The `l[1]` takes the list passed to the lambda and returns the second item (subscript `[1]` is the second item...) – dawg Dec 13 '20 at 16:39
22

To sort a list of lists on the second column, use operator.itemgetter() for ease and clarity:

from operator import itemgetter
outputlist = sorted(inputlist, key=itemgetter(1), reverse=True)

or, to sort in-place:

from operator import itemgetter
inputlist.sort(key=itemgetter(1), reverse=True)

itemgetter() is a little faster than using a lambda for the task.

Demo:

>>> from operator import itemgetter
>>> inputlist = [
...     [1, 0.23],
...     [2, 0.39],
...     [4, 0.31],
...     [5, 0.27],
... ]
>>> sorted(inputlist, key=itemgetter(1), reverse=True)
[[2, 0.39], [4, 0.31], [5, 0.27], [1, 0.23]]

You'd only see your exception if you had floating point values in your inputlist directly:

>>> inputlist.append(4.2)
>>> inputlist
[[1, 0.23], [2, 0.39], [4, 0.31], [5, 0.27], 4.2]
>>> sorted(inputlist, key=itemgetter(1), reverse=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'float' object is not subscriptable

(for Python 3; Python 2's error message is slightly different, resulting in TypeError: 'float' object has no attribute '__getitem__' instead).

This is because the itergetter(1) call is applied to all elements in the outer list but only works on nested ordered sequences, not on the one floating point value now added.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343