tags:

views:

145

answers:

4

What is the best way to sort a list of floats by their value, whiles still keeping record of the initial order.

I.e. sorting a:

a=[2.3, 1.23, 3.4, 0.4]

returns something like

a_sorted = [0.4, 1.23, 2.3, 3.4]
a_order = [4, 2, 1, 3]

If you catch my drift.

+10  A: 

You could do something like this:

>>> sorted(enumerate(a), key=lambda x: x[1])
[(3, 0.4), (1, 1.23), (0, 2.3), (2, 3.4)]

If you need to indexing to start with 1 instead of 0, enumerate accepts the second parameter.

SilentGhost
+1 for using enumerate!
GWW
`aorder, asorted = zip(*sorted(enumerate(a), key=lambda x: x[1])` for completeness.
carl
I'd be pretty sure, OP would need to zip his two lists back at one stage.
SilentGhost
itemgetter would have been better than lambda
dugres
@dugres: huh? why is that? I'm no fan of lambdas, but if they have a use in python it's here.
SilentGhost
@SilentGhost: itemgetter, also, has many use and this is a good one. **key=itemgetter(1)**
dugres
@dugres: you meant “`operator.itemgetter` *might* be *faster* than `lambda`, although not necessarily in a perceptible way”.
ΤΖΩΤΖΙΟΥ
@ΤΖΩΤΖΙΟΥ : It might be faster or not, in this case I don't know, that's not the point here. To me, it's just the reason **itemgetter** exists in the first place ; if you don't use it here, you will never use it.
dugres
@dugres: well, I don't :)
SilentGhost
+4  A: 
  • Use enumerate to generate the sequence numbers.
  • Use sorted with a key to sort by the floats
  • Use zip to separate out the order from the values

For example:

a_order, a_sorted = zip(*sorted(enumerate(a), key=lambda item: item[1]))
Daniel Stutzbach
+2  A: 

If you have numpy installed:

import numpy
a=[2.3, 1.23, 3.4, 0.4]
a_sorted = numpy.sorted(a)
a_order = numpy.argsort(a)
pberkes
This is nice for a guy more used to matlab then python =)
Theodor
A: 
from itertools import izip
a_order, a_sorted = [list(b) for b in izip(*sorted(enumerate(a, 1), key=lambda n: n[1]))]
Franck