tags:

views:

102

answers:

2

hi is there a build'in function of python that does on python.array what argsort() does on a numpy.array?

+11  A: 

There is no built-in function, but it's easy to assemble one out of the terrific tools Python makes available:

def argsort(seq):
    # http://stackoverflow.com/questions/3071415/efficient-method-to-calculate-the-rank-vector-of-a-list-in-python
    return sorted(range(len(seq)), key=seq.__getitem__)

x=[5,2,1,10]

print(argsort(x))
# [2, 1, 0, 3]

It works on Python array.arrays the same way:

import array
x=array.array('d', [5, 2, 1, 10])
print(argsort(x))
# [2, 1, 0, 3]
unutbu
+1 Very Pythonic!
katrielalex
Instead of using the (theoretically private) __getitem__, you can also use `operator.itemgetter` / `operator.attrgetter` http://docs.python.org/library/operator.html
Ender
If `operator.itemgetter` could be used as a drop-in replacement for `__getitem__`, I think I'd agreed with you Ender, but as far as I can see, `operator.itemgetter` would also require wrapping it in a `lambda` expression. I'd rather avoid the extra `lambda` if I could.
unutbu
A: 

My alternative with enumerate:

def argsort(seq):
    return [x for x,y in sorted(enumerate(seq), key = lambda x: x[1])]

seq=[5,2,1,10]
print(argsort(seq))
# Output:
# [2, 1, 0, 3]

Better though to use answer from http://stackoverflow.com/users/9990/marcelo-cantos answer to thread http://stackoverflow.com/questions/3407414/python-sort-without-lambda-expressions

[i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))]
Tony Veijalainen