To stare pytanie, ale niektóre odpowiedzi, które widzę, nie są w rzeczywistości skuteczne, ponieważ zip
nie można ich skryptować. Inne odpowiedzi nie przeszkadzały import operator
i podają więcej informacji o tym module i jego zaletach tutaj.
Istnieją co najmniej dwa dobre idiomy dotyczące tego problemu. Począwszy od podanego przykładowego wejścia:
X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1 ]
Jest to również znane jako Schwartzian_transform po R. Schwartz, który spopularyzował ten wzór w Perlu w latach 90.:
# Zip (decorate), sort and unzip (undecorate).
# Converting to list to script the output and extract X
list(zip(*(sorted(zip(Y,X)))))[1]
# Results in: ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')
Zauważ, że w tym przypadku Y
i X
są klasyfikowane i porównano leksykograficznie. Oznacza to, że pierwsze pozycje (od Y
) są porównywane; a jeśli są takie same, wówczas X
porównywane są drugie elementy (z ) i tak dalej. Może to tworzyć niestabilne dane wyjściowe, chyba że podasz oryginalne indeksy listy dla porządku leksykograficznego, aby zachować duplikaty w ich oryginalnej kolejności.
Zapewnia to większą bezpośrednią kontrolę nad sposobem sortowania danych wejściowych, dzięki czemu można uzyskać stabilność sortowania , po prostu określając konkretny klucz do sortowania. Zobacz więcej przykładów tutaj .
import operator
# Sort by Y (1) and extract X [0]
list(zip(*sorted(zip(X,Y), key=operator.itemgetter(1))))[0]
# Results in: ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')