Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sort a python list based on multiple criteria [duplicate]

I have a list whose elements are dictionaries with a value and a type field, i.e.:

my_list = [{'val':5, 'type':0},{'val':6, 'type':2},{'val':2, 'type':1},{'val':9, 'type':0}]

I would like to sort this list in descending order based on the type field and within each type based on the value field, and obtain a vector with the corresponding indexes of the sorting along with the sorted vector.

I know how to do it for an individual criteria using a lambda function, i.e.:

sorted_list = sorted(my_list, key=lambda k: k['type'], reverse=True) 

but how do I extend it to multiple criteria?

Desired output:

 sorted_list = [{'val':6, 'type':2},{'val':2, 'type':1},{'val':9, 'type':0},{'val':5, 'type':0}]

 sorted_idxs = [1, 2, 3, 0]`, such that `[my_list[k] for k in sorted_idxs]==sorted_list
like image 320
Matteo Avatar asked Jan 06 '23 04:01

Matteo


1 Answers

If the key returns a tuple, sorted will consider them in order when sorting:

In [3]: sorted(my_list, key=lambda k: (k['type'], k['val']), reverse=True)
Out[3]:
[{'type': 2, 'val': 6},
 {'type': 1, 'val': 2},
 {'type': 0, 'val': 9},
 {'type': 0, 'val': 5}]

If you want the indices, just throw an enumerate in there as well:

In [7]: sorted(enumerate(my_list), key=lambda k: (k[1]['type'], k[1]['val']), reverse=True)
Out[7]:
[(1, {'type': 2, 'val': 6}),
 (2, {'type': 1, 'val': 2}),
 (3, {'type': 0, 'val': 9}),
 (0, {'type': 0, 'val': 5})]

In [8]: [k for k, v in sorted(enumerate(my_list), key=lambda k: (k[1]['type'], k[1]['val']), reverse=True)]
Out[8]: [1, 2, 3, 0]
like image 178
Randy Avatar answered Jan 14 '23 07:01

Randy