2010-08-01 14 views

Antwort

35

ich die oben genannten Vorschläge und meine Ergebnisse hier sind zeitlich fädeln.

Zunächst einmal die Funktionen:

def f(seq): 
    # http://stackoverflow.com/questions/3382352/equivalent-of-numpy-argsort-in-basic-python/3383106#3383106 
    #non-lambda version by Tony Veijalainen 
    return [i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))] 

def g(seq): 
    # http://stackoverflow.com/questions/3382352/equivalent-of-numpy-argsort-in-basic-python/3383106#3383106 
    #lambda version by Tony Veijalainen 
    return [x for x,y in sorted(enumerate(seq), key = lambda x: x[1])] 


def h(seq): 
    #http://stackoverflow.com/questions/3382352/equivalent-of-numpy-argsort-in-basic-python/3382369#3382369 
    #by unutbu 
    return sorted(range(len(seq)), key=seq.__getitem__) 

nun die IPython Sitzung:

In [16]: seq = rand(10000).tolist() 

In [17]: %timeit f(seq) 
100 loops, best of 3: 10.5 ms per loop 

In [18]: %timeit g(seq) 
100 loops, best of 3: 8.83 ms per loop 

In [19]: %timeit h(seq) 
100 loops, best of 3: 6.44 ms per loop 

FWIW

+3

Interessant - wahrscheinlich ist der Durchschnitt wichtiger als die "Beste" von 3 (?) – JPH

+1

Der Durchschnitt wird durch Ausreißer beeinflusst.Sie ​​wollen nicht, dass die Ergebnisse durch andere laufende Programme oder Hardware-Cache-Misses verschmutzt werden Zufälligkeiten. –

51

Es gibt keine integrierte Funktion, aber es ist einfach eine von den tollen Werkzeugen zu montieren Python zur Verfügung stellt:

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] 

Es ist auf Python arbeitet array.array s die gleiche Art und Weise:

import array 
x = array.array('d', [5, 2, 1, 10]) 
print(argsort(x)) 
# [2, 1, 0, 3] 
+4

+1 Sehr Pythonic! – katrielalex

+1

Anstatt das (theoretisch private) __getitem__ zu verwenden, können Sie auch 'operator.itemgetter' /' operator.attrgetter' verwenden. Http://docs.python.org/library/operator.html – Ender

+0

Wenn 'operator.itemgetter' sein könnte als ein Ersatz für "__getitem__" verwendet, glaube ich, dass ich mit dir Ender einverstanden war, aber soweit ich das sehen kann, würde 'operator.itemgetter' auch erfordern, dass es in einen 'Lambda'-Ausdruck eingebunden wird. Ich würde lieber das zusätzliche 'Lambda' vermeiden, wenn ich könnte. – unutbu

2

diese Frage gefunden, aber benötigt argsort für eine Liste von Objekten basierend auf eine Objekteigenschaft

Erweiterung unutbu Antwort, dies wäre:

sorted(range(len(seq)), key = lambda x: seq[x].sort_property)