0

Assume I want to sort a list of lists like explained here:

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

(Or with lambda.) Now I have a second list which I want to sort in the same order, so I need the new order of the indices. sorted() or .sort() do not return indices. How can I do that?

Actually in my case both lists contain numpy arrays. But the numpy sort/argsort aren't intuitive for that case either.

quarky
  • 333
  • 1
  • 2
  • 12
  • what is the desired output _finally_? – Ma0 Aug 22 '17 at 09:11
  • I'd say the first step would be to give us a complete example. I don't see a second list. And I don't see numpy, either. – Stefan Pochmann Aug 22 '17 at 09:11
  • So based on the shifting performed on the first `list`, order a second one? If yes, `zip` them before ordering. – Ma0 Aug 22 '17 at 09:12
  • Could you show your second list and the expected output, to make this clearer? If your second list was `[1,2,3]`, you want to sort it as `[3,1,2]`, right? – tobias_k Aug 22 '17 at 09:13
  • Perhaps: [Sorting list based on values from another list?](https://stackoverflow.com/questions/6618515/sorting-list-based-on-values-from-another-list) – Ashwini Chaudhary Aug 22 '17 at 09:13
  • You could e.g. either sort the enumeration of the list to get the new order of the indices, or sort the zipped lists and then unzip. – tobias_k Aug 22 '17 at 09:13

3 Answers3

2

If I understood you correctly, you want to order B in the example below, based on a sorting rule you apply on L. Take a look at this:

L = [[0, 1, 'f'], [4, 2, 't'], [9, 4, 'afsd']]
B = ['a', 'b', 'c']

result = [i for _, i in sorted(zip(L, B), key=lambda x: x[0][2])]
print(result)  # ['c', 'a', 'b']
# that corresponds to [[9, 4, 'afsd'], [0, 1, 'f'], [4, 2, 't']]
Ma0
  • 15,057
  • 4
  • 35
  • 65
1

If I understand correctly, you want to know how the list has been rearranged. i.e. where is the 0th element after sorting, etc.

If so, you are one step away:

L2 = [L.index(x) for x in sorted(L, key=itemgetter(2))]

which gives:

[2, 0, 1]

As tobias points out, this is needlessly complex compared to

map(itemgetter(0),  sorted(enumerate(L), key=lambda x: x[1][2]))
greg_data
  • 2,247
  • 13
  • 20
  • 1
    For longer lists, this is very wasteful, having O(n²) complexity. Better use `sorted(enumerate(...))` – tobias_k Aug 22 '17 at 09:15
0

NumPy

Setup:

import numpy as np
L = np.array([[0, 1, 'f'], [4, 2, 't'], [9, 4, 'afsd']])
S = np.array(['a', 'b', 'c'])

Solution:

print S[L[:,2].argsort()]

Output:

['c' 'a' 'b']

Just Python

You could combine both lists, sort them together, and separate them again.

>>> L = [[0, 1, 'f'], [4, 2, 't'], [9, 4, 'afsd']]
>>> S = ['a', 'b', 'c']
>>> L, S = zip(*sorted(zip(L, S), key=lambda x: x[0][2]))
>>> L
([9, 4, 'afsd'], [0, 1, 'f'], [4, 2, 't'])
>>> S
('c', 'a', 'b')

I guess you could do something similar in NumPy as well...

Stefan Pochmann
  • 27,593
  • 8
  • 44
  • 107