308

I have a list of lists. For example,

[
[0,1,'f'],
[4,2,'t'],
[9,4,'afsd']
]

If I wanted to sort the outer list by the string field of the inner lists, how would you do that in python?

John La Rooy
  • 295,403
  • 53
  • 369
  • 502
oldspice
  • 3,273
  • 3
  • 17
  • 8

12 Answers12

397

This is a job for itemgetter

>>> from operator import itemgetter
>>> L=[[0, 1, 'f'], [4, 2, 't'], [9, 4, 'afsd']]
>>> sorted(L, key=itemgetter(2))
[[9, 4, 'afsd'], [0, 1, 'f'], [4, 2, 't']]

It is also possible to use a lambda function here, however the lambda function is slower in this simple case

John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • What if I would want to ignore case? – bzupnick Jul 29 '13 at 11:31
  • 8
    @bzupnick, use `key=lambda x:x[2].casefold()`. If your Python isn't new enough, just use `.lower()` instead of `.casefold()` – John La Rooy Jul 29 '13 at 11:52
  • x = [[[5,3],1.0345],[[5,6],5.098],[[5,4],4.89],[[5,1],5.97]] With a list like this is can we sort using itemgetter() with respect to elements in x[0][1] ? – nidHi Dec 02 '16 at 09:48
  • Can I also get the indices of the sort, so to sort another related list of lists in the same order? – quarky Aug 22 '17 at 08:52
  • @quaryk It sounds like an interesting question, but not suitable to answer in the comments. If you can't find a question that covers it, you should create one. – John La Rooy Aug 23 '17 at 00:13
  • Is a `lambda` function really slower ? In the source code, `itemgetter` seems to work the same way... – Axel Puig Dec 05 '18 at 23:48
  • @AxelPuig, it's not hard to check. I get 772ns for the itemgetter and 849ns for a lambda function. The relative difference seems to get worse for the `lambda` as `L` gets longer – John La Rooy Dec 06 '18 at 00:00
  • I was using a `lambda` solution until I learned `itemgetter()` is faster. – Mr. Lance E Sloan Aug 25 '22 at 15:34
252

in place

>>> l = [[0, 1, 'f'], [4, 2, 't'], [9, 4, 'afsd']]
>>> l.sort(key=lambda x: x[2])

not in place using sorted:

>>> sorted(l, key=lambda x: x[2])
mouad
  • 67,571
  • 18
  • 114
  • 106
99

Itemgetter lets you to sort by multiple criteria / columns:

sorted_list = sorted(list_to_sort, key=itemgetter(2,0,1))
fider
  • 1,976
  • 26
  • 29
  • 5
    I think this answer is very important. I think people trying to sort by inner array indexes will fall here but people looking to sort by MULTIPLE inner array indexes will start here and your answer helped me see that itemgetter will actually do that for you! – ZekeDroid Oct 09 '14 at 16:55
21

multiple criteria can also be implemented through lambda function

sorted_list = sorted(list_to_sort, key=lambda x: (x[1], x[0]))
Rahul Kumar
  • 271
  • 3
  • 12
15
array.sort(key = lambda x:x[1])

You can easily sort using this snippet, where 1 is the index of the element.

Abhi
  • 1,127
  • 1
  • 12
  • 25
8

Like this:

import operator
l = [...]
sorted_list = sorted(l, key=operator.itemgetter(desired_item_index))
Jim Brissom
  • 31,821
  • 4
  • 39
  • 33
8

I think lambda function can solve your problem.

old_list = [[0,1,'f'], [4,2,'t'],[9,4,'afsd']]

#let's assume we want to sort lists by last value ( old_list[2] )
new_list = sorted(old_list, key=lambda x: x[2])

#Resulst of new_list will be:

[[9, 4, 'afsd'], [0, 1, 'f'], [4, 2, 't']]
Tushar Niras
  • 3,654
  • 2
  • 22
  • 24
2

More easy to understand (What is Lambda actually doing):

ls2=[[0,1,'f'],[4,2,'t'],[9,4,'afsd']]
def thirdItem(ls):
    #return the third item of the list
    return ls[2]
#Sort according to what the thirdItem function return 
ls2.sort(key=thirdItem)
Aghiad Alzein
  • 159
  • 1
  • 6
2
**old_list = [[0,1,'f'], [4,2,'t'],[9,4,'afsd']]
    #let's assume we want to sort lists by last value ( old_list[2] )
    new_list = sorted(old_list, key=lambda x: x[2])**

correct me if i'm wrong but isnt the 'x[2]' calling the 3rd item in the list, not the 3rd item in the nested list? should it be x[2][2]?

  • No, because key/lambda is already iterating over the items in the first-level list. x is a local variable bound to each item in turn. – DragonLord Jun 06 '20 at 16:38
2

Sorting a Multidimensional Array [execute here][1]

points=[[2,1],[1,2],[3,5],[4,5],[3,1],[5,2],[3,8],[1,9],[1,3]]

def getKey(x):
   return [x[0],-x[1]]

points.sort(key=getKey)

print(points)
Nishan B
  • 627
  • 7
  • 11
  • if you can explain the function getKey, that'd be great. from my Understanding ig, you're sorting according to the second sublist variable in descending order. correct me if I'm wrong. – Anirudh Ganesh Apr 15 '22 at 03:26
  • 1
    sort method will sort the array in ascending order so when you pass first key as positive it'll sort in ascending and for second key it's -ve so we're altering sort to be in decreasing order for same elements – Nishan B Apr 21 '22 at 08:58
0

Make sure that you do not have any null or NaN values in the list you want to sort. If there are NaN values, then your sort will be off, impacting the sorting of the non-null values.

Check out Python: sort function breaks in the presence of nan

NicoNu
  • 1
  • 1
0

Using a custom key function you can easily sort any list of lists as you want:

L = [[0,1,'f'], [4,2,'t'], [9,4,'afsd']]

def sorter(lst):
    return lst[2].casefold()

L.sort(key=sorter)

# result: [[9, 4, 'afsd'], [0, 1, 'f'], [4, 2, 't']]