4

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
Siva Shanmugam
  • 662
  • 9
  • 19
Matteo
  • 7,924
  • 24
  • 84
  • 129
  • Once you have the indexes, you can generate the sorted list yourself. The reverse isn't true. – Mark Ransom Oct 24 '16 at 15:44
  • 1
    And the answer that the duplicate doesn't give you: http://stackoverflow.com/questions/6422700/how-to-get-indices-of-a-sorted-array-in-python – Mark Ransom Oct 24 '16 at 15:49

1 Answers1

9

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]
Randy
  • 14,349
  • 2
  • 36
  • 42
  • 1
    `sorted_ids, sorted_list = zip(*[(i, x) for sorted(enumerate(my_list), key=lambda j, d: (d['type'], d['val']), reverse=True)])` can seperate the two into seperate lists – Patrick Haugh Oct 24 '16 at 15:52