Sortierliste basierend auf Werten aus einer anderen Liste

Lesezeit: 6 Minuten

Benutzer-Avatar
Legende

Ich habe eine Liste von Zeichenfolgen wie diese:

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,   0,   1,   2,   2,   0,   1 ]

Was ist der kürzeste Weg, X mit Werten aus Y zu sortieren, um die folgende Ausgabe zu erhalten?

["a", "d", "h", "b", "c", "e", "i", "f", "g"]

Die Reihenfolge der Elemente mit gleichem “Schlüssel” spielt keine Rolle. Ich kann auf die Verwendung von zurückgreifen for Konstrukte, aber ich bin gespannt, ob es einen kürzeren Weg gibt. Irgendwelche Vorschläge?

  • Die Antwort von riza könnte beim Plotten von Daten nützlich sein, da zip(*sorted(zip(X, Y), key=lambda pair: pair[0])) gibt sowohl das sortierte X als auch Y sortiert mit den Werten von X zurück.

    – jojo

    15. Mai 2014 um 12:37 Uhr


  • Allgemeinerer Fall (Liste Y nach einem beliebigen Schlüssel statt der Standardreihenfolge sortieren)

    – Benutzer202729

    1. Oktober 2020 um 8:37 Uhr


Benutzer-Avatar
Was auch immer

Kürzester Code

[x for _, x in sorted(zip(Y, X))]

Beispiel:

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

Z = [x for _,x in sorted(zip(Y,X))]
print(Z)  # ["a", "d", "h", "b", "c", "e", "i", "f", "g"]

Allgemein gesagt

[x for _, x in sorted(zip(Y, X), key=lambda pair: pair[0])]

Erklärt:

  1. zip die Zwei lists.
  2. Erstellen Sie eine neue, sortierte list basierend auf zip verwenden sorted().
  3. Verwenden eines Listenverständnisses Extrakt die ersten Elemente jedes Paares aus dem sortierten, gezippten list.

Weitere Informationen zum Festlegen\Verwenden der key Parameter sowie die sorted Funktion im Allgemeinen, werfen Sie einen Blick auf Dies.


  • Dies ist richtig, aber ich füge den Hinweis hinzu, dass dies nicht unbedingt wie erwartet funktioniert, wenn Sie versuchen, mehrere Arrays nach demselben Array zu sortieren, da der zum Sortieren verwendete Schlüssel (y, x) ist. , nicht nur y. Sie sollten stattdessen verwenden [x for (y,x) in sorted(zip(Y,X), key=lambda pair: pair[0])]

    – gms7777

    17. Januar 2014 um 20:33 Uhr

  • gute Lösung! Aber es sollte so sein: Die Liste ist nach dem ersten Element der Paare geordnet, und die Comprehension extrahiert das ‘zweite’ Element der Paare.

    – MasterControlProgramm

    6. Oktober 2017 um 14:31 Uhr

  • Diese Lösung ist schlecht, wenn es um die Lagerung geht. Wann immer möglich, wird eine In-Place-Sortierung bevorzugt.

    – Hassfeind

    30. Juni 2019 um 16:27 Uhr

  • @Hatefiend interessant, könntest du auf eine Referenz verweisen, wie man das erreicht?

    – RichieV

    3. September 2020 um 3:18 Uhr

  • @RichieV Ich empfehle die Verwendung von Quicksort oder einer In-Place-Merge-Sort-Implementierung. Sobald Sie das haben, definieren Sie Ihre eigene Vergleichsfunktion, die Werte basierend auf den Indizes der Liste vergleicht Y. Das Endergebnis sollte eine Liste sein Y unberührt und Liste X in die erwartete Lösung geändert werden, ohne jemals eine temporäre Liste erstellen zu müssen.

    – Hassfeind

    9. September 2020 um 5:26 Uhr

Zippen Sie die beiden Listen zusammen, sortieren Sie sie und nehmen Sie dann die gewünschten Teile:

>>> yx = zip(Y, X)
>>> yx
[(0, 'a'), (1, 'b'), (1, 'c'), (0, 'd'), (1, 'e'), (2, 'f'), (2, 'g'), (0, 'h'), (1, 'i')]
>>> yx.sort()
>>> yx
[(0, 'a'), (0, 'd'), (0, 'h'), (1, 'b'), (1, 'c'), (1, 'e'), (1, 'i'), (2, 'f'), (2, 'g')]
>>> x_sorted = [x for y, x in yx]
>>> x_sorted
['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

Kombiniere diese miteinander, um Folgendes zu erhalten:

[x for y, x in sorted(zip(Y, X))]

  • Das ist in Ordnung, wenn X ist eine Liste von straber seien Sie vorsichtig, wenn die Möglichkeit besteht, dass < ist für einige Elementpaare in nicht definiert XzB – wenn einige von ihnen waren None

    – John LaRooy

    23. August 2017 um 5:05 Uhr

  • Wenn wir versuchen, sort über ein Zip-Objekt zu verwenden, AttributeError: 'zip' object has no attribute 'sort' ist das, was ich jetzt bekomme.

    – Ash Upadhyay

    23. Januar 2018 um 12:57 Uhr


  • Sie verwenden Python 3. In Python 2 hat zip eine Liste erstellt. Jetzt erzeugt es ein iterierbares Objekt. sorted(zip(...)) sollte noch funktionieren, oder: them = list(zip(...)); them.sort()

    – Ned Batchelder

    23. Januar 2018 um 16:38 Uhr

Auch wenn es Ihnen nichts ausmacht, numpy-Arrays zu verwenden (oder sich bereits mit numpy-Arrays befassen …), hier ist eine weitere nette Lösung:

people = ['Jim', 'Pam', 'Micheal', 'Dwight']
ages = [27, 25, 4, 9]

import numpy
people = numpy.array(people)
ages = numpy.array(ages)
inds = ages.argsort()
sortedPeople = people[inds]

Ich habe es hier gefunden:
http://scienceoss.com/sort-one-list-by-another-list/

  • Für größere Arrays / Vektoren ist diese Lösung mit numpy von Vorteil!

    – MasterControlProgramm

    6. Oktober 2017 um 14:53 Uhr


  • Wenn es sich bereits um numpy-Arrays handelt, ist es einfach sortedArray1= array1[array2.argsort()]. Und das macht es auch einfach, mehrere Listen nach einer bestimmten Spalte eines 2D-Arrays zu sortieren: zB sortedArray1= array1[array2[:,2].argsort()] um array1 (das mehrere Spalten haben kann) nach den Werten in der dritten Spalte von array2 zu sortieren.

    – Aaron Bramson

    12. Juni 2018 um 8:50 Uhr

Benutzer-Avatar
Absender

Die naheliegendste Lösung für mich ist die Verwendung von key Schlüsselwort arg.

>>> X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
>>> Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]
>>> keydict = dict(zip(X, Y))
>>> X.sort(key=keydict.get)
>>> X
['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

Beachten Sie, dass Sie dies zu einem Einzeiler verkürzen können, wenn Sie Folgendes möchten:

>>> X.sort(key=dict(zip(X, Y)).get)

Wie Wenmin Mu und Jack Peng betont haben, setzt dies voraus, dass die Werte in X sind alle verschieden. Das geht ganz einfach mit einer Indexliste:

>>> Z = ["A", "A", "C", "C", "C", "F", "G", "H", "I"]
>>> Z_index = list(range(len(Z)))
>>> Z_index.sort(key=keydict.get)
>>> Z = [Z[i] for i in Z_index]
>>> Z
['A', 'C', 'H', 'A', 'C', 'C', 'I', 'F', 'G']

Da der von Whatang beschriebene Ansatz zum Dekorieren-Sortieren-Nicht-Dekorieren etwas einfacher ist und in allen Fällen funktioniert, ist er wahrscheinlich die meiste Zeit besser. (Dies ist eine sehr alte Antwort!)

Benutzer-Avatar
pylang

more_itertools hat ein Tool zum parallelen Sortieren von Iterables:

Gegeben

from more_itertools import sort_together


X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

Demo

sort_together([Y, X])[1]
# ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')

  • Ich mag das, weil ich mehrere Listen mit einem Index erstellen kann sort_together([Index,X,Y,Z])

    – Tunnelbauer

    23. Oktober 2021 um 14:02 Uhr


  • Oh, ignorieren, ich kann auch sorted(zip(Index,X,Y,Z)) machen.

    – Tunnelbauer

    23. Oktober 2021 um 14:19 Uhr

Benutzer-Avatar
nackjicholson

Ich bin eigentlich hierher gekommen, um eine Liste nach einer Liste zu sortieren, in der die Werte übereinstimmen.

list_a = ['foo', 'bar', 'baz']
list_b = ['baz', 'bar', 'foo']
sorted(list_b, key=lambda x: list_a.index(x))
# ['foo', 'bar', 'baz']

  • Ich mag das, weil ich mehrere Listen mit einem Index erstellen kann sort_together([Index,X,Y,Z])

    – Tunnelbauer

    23. Oktober 2021 um 14:02 Uhr


  • Oh, ignorieren, ich kann auch sorted(zip(Index,X,Y,Z)) machen.

    – Tunnelbauer

    23. Oktober 2021 um 14:19 Uhr

Eine weitere Alternative, bei der mehrere der Antworten kombiniert werden.

zip(*sorted(zip(Y,X)))[1]

Um für Python3 zu arbeiten:

list(zip(*sorted(zip(B,A))))[1]

1120630cookie-checkSortierliste basierend auf Werten aus einer anderen Liste

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy