Wie sortiere ich eine Liste / ein Tupel von Listen / Tupeln nach dem Element an einem bestimmten Index?

657

Ich habe einige Daten entweder in einer Liste von Listen oder einer Liste von Tupeln, wie folgt:

data = [[1,2,3], [4,5,6], [7,8,9]]
data = [(1,2,3), (4,5,6), (7,8,9)]

Und ich möchte nach dem 2. Element in der Teilmenge sortieren. Das heißt, Sortieren nach 2,5,8, woher 2kommt (1,2,3), 5kommt von (4,5,6). Was ist der übliche Weg, dies zu tun? Soll ich Tupel oder Listen in meiner Liste speichern?

Stan
quelle
51
In Bezug auf "Soll ich Tupel oder Listen in meiner Liste speichern?" Lautet die Faustregel, die Dinge so unveränderlich wie möglich zu machen. Wenn Sie die vorhandenen Unterlisten nicht ändern müssen , erstellen Sie sie zu Tupeln.
Matthew Flaschen

Antworten:

1112
sorted_by_second = sorted(data, key=lambda tup: tup[1])

oder:

data.sort(key=lambda tup: tup[1])  # sorts in place
Stephen
quelle
10
Irgendeine Idee, wie man es größer zu kleiner sortiert?
Billwild
63
@billwild: Hilfe (sortiert). reverse = True.
Stephen
34
@ Stephen mit itemgetter ist schneller und einfacher: key=itemgetter(1)und am Anfang der Datei:from operator import itemgetter
Joschua
3
@Cemre wie im zweiten Beispiel ist sorthier eine ListObjektmethode von Python, die eine Lambda-Funktion als keyParameter erhält . Sie können es als tupoder oder toder was auch immer Sie mögen benennen und es wird immer noch funktionieren. tupHier wird der Index des Tupels der Liste angegeben. Dies 1bedeutet, dass die Sortierung nach den zweiten Werten der Tupel aus der ursprünglichen Liste ( 2, 5, 8) durchgeführt wird.
Neurotransmitter
1
Ich war leicht skeptisch gegenüber der unbegründeten Behauptung, dass "die Verwendung von Itemgetter schneller und einfacher ist". Während ich den intuitiven lambdaAnsatz subjektiv als einfacher als die unintuitive itemgetterKlasse betrachte, itemgetter scheint er tatsächlich schneller zu sein . Ich bin gespannt, warum das so ist. Mein grober Verdacht ist, dass a lambdadie versteckten Kosten für die Erfassung aller lokalen Variablen in einem Abschlusskontext verursacht, während dies bei einer itemgetterInstanz nicht der Fall ist. tl; dr: Immer verwenden itemgetter, weil die Geschwindigkeit gewinnt.
Cecil Curry
235
from operator import itemgetter
data.sort(key=itemgetter(1))
Manova
quelle
37
Dies sollte die akzeptierte Antwort sein. Siehe auch Charlie ‚s geschrieben Timings , die demonstrieren itemgetterKlasse zu sortieren 126% schneller als im Durchschnitt der äquivalente lambdaFunktion.
Cecil Curry
9
Sie können auch hierarchisch nach mehreren Indizes sortieren, z. B.data.sort(key=itemgetter(3,1))
Michael Ohlrogge
57

Ich möchte nur zu Stephens Antwort hinzufügen, wenn Sie das Array von hoch nach niedrig sortieren möchten. Eine andere Möglichkeit als in den obigen Kommentaren besteht darin, dies der Zeile hinzuzufügen:

reverse = True

und das Ergebnis wird wie folgt sein:

data.sort(key=lambda tup: tup[1], reverse=True)
Sifoo
quelle
48

Zum Sortieren nach mehreren Kriterien, nämlich zum Beispiel nach dem zweiten und dritten Element in einem Tupel, sei

data = [(1,2,3),(1,2,1),(1,1,4)]

Definieren Sie daher ein Lambda, das beispielsweise ein Tupel zurückgibt, das die Priorität beschreibt

sorted(data, key=lambda tup: (tup[1],tup[2]) )
[(1, 1, 4), (1, 2, 1), (1, 2, 3)]
Ulme
quelle
28

Stephens Antwort ist die, die ich verwenden würde. Der Vollständigkeit halber hier das DSU-Muster (Decorate-Sort-Undecorate) mit Listenverständnis:

decorated = [(tup[1], tup) for tup in data]
decorated.sort()
undecorated = [tup for second, tup in decorated]

Oder knapper:

[b for a,b in sorted((tup[1], tup) for tup in data)]

Wie im Python Sorting HowTo erwähnt , war dies seit Python 2.4, als Schlüsselfunktionen verfügbar wurden, nicht mehr erforderlich .

tcarobruce
quelle
2
Diese Antwort ist also nützlich für Python 2.3-? Gibt es in aktuelleren Python-Versionen gültige Verwendungszwecke, auf die Sie möglicherweise näher eingehen? Wenn nicht, keine Mühe ... kam gerade vorbei, sah dies und der alte Noggin musste nur ein kleines bisschen herumwirbeln. Wie auch immer, Prost und danke für diesen Spaziergang zurück in die früheren Tage von Python.
mechanisches
19

Um eine Liste von Tupeln zu sortieren (<word>, <count>), für countin absteigender Reihenfolge und wordin alphabetischer Reihenfolge:

data = [
('betty', 1),
('bought', 1),
('a', 1),
('bit', 1),
('of', 1),
('butter', 2),
('but', 1),
('the', 1),
('was', 1),
('bitter', 1)]

Ich benutze diese Methode:

sorted(data, key=lambda tup:(-tup[1], tup[0]))

und es gibt mir das Ergebnis:

[('butter', 2),
('a', 1),
('betty', 1),
('bit', 1),
('bitter', 1),
('bought', 1),
('but', 1),
('of', 1),
('the', 1),
('was', 1)]
Ich mingzhi
quelle
1
Was ist, wenn tup [1] eine Zeichenfolge ist?
Eric
12

Ohne Lambda:

def sec_elem(s):
    return s[1]

sorted(data, key=sec_elem)
Mesco
quelle
9

itemgetter()ist etwas schneller als lambda tup: tup[1], aber der Anstieg ist relativ gering (etwa 10 bis 25 Prozent).

(IPython-Sitzung)

>>> from operator import itemgetter
>>> from numpy.random import randint
>>> values = randint(0, 9, 30000).reshape((10000,3))
>>> tpls = [tuple(values[i,:]) for i in range(len(values))]

>>> tpls[:5]    # display sample from list
[(1, 0, 0), 
 (8, 5, 5), 
 (5, 4, 0), 
 (5, 7, 7), 
 (4, 2, 1)]

>>> sorted(tpls[:5], key=itemgetter(1))    # example sort
[(1, 0, 0), 
 (4, 2, 1), 
 (5, 4, 0), 
 (8, 5, 5), 
 (5, 7, 7)]

>>> %timeit sorted(tpls, key=itemgetter(1))
100 loops, best of 3: 4.89 ms per loop

>>> %timeit sorted(tpls, key=lambda tup: tup[1])
100 loops, best of 3: 6.39 ms per loop

>>> %timeit sorted(tpls, key=(itemgetter(1,0)))
100 loops, best of 3: 16.1 ms per loop

>>> %timeit sorted(tpls, key=lambda tup: (tup[1], tup[0]))
100 loops, best of 3: 17.1 ms per loop
Walter
quelle
In der Itemgetter-Sortierlösung finden Sie Informationen zum Variieren von umgekehrten Argumenten für mehrere Spalten. Anschließend müssen Sie Ihre Sortierung in mehreren Schritten hintereinander anordnen
Lorenz,
6

@ Stephens Antwort ist auf den Punkt! Hier ist ein Beispiel für eine bessere Visualisierung:

Grüße die Fans von Ready Player One! =)

>>> gunters = [('2044-04-05', 'parzival'), ('2044-04-07', 'aech'), ('2044-04-06', 'art3mis')]
>>> gunters.sort(key=lambda tup: tup[0])
>>> print gunters
[('2044-04-05', 'parzival'), ('2044-04-06', 'art3mis'), ('2044-04-07', 'aech')]

keyist eine Funktion, die aufgerufen wird, um die Elemente der Sammlung zum Vergleich zu transformieren. like compareToMethode in Java.

Der an key übergebene Parameter muss aufrufbar sein. Hier lambdaerzeugt die Verwendung von eine anonyme Funktion (die aufrufbar ist).
Die Syntax von Lambda ist das Wort Lambda, gefolgt von einem iterierbaren Namen und einem einzelnen Codeblock.

Im folgenden Beispiel sortieren wir eine Liste von Tupeln, die die Informationen zum Zeitpunkt eines bestimmten Ereignisses und des Darstellernamens enthalten.

Wir sortieren diese Liste nach dem Zeitpunkt des Auftretens des Ereignisses - dem 0. Element eines Tupels.

Hinweis - s.sort([cmp[, key[, reverse]]]) sortiert die Elemente von s an Ort und Stelle

Rishi
quelle
-5

Das Sortieren eines Tupels ist ganz einfach:

tuple(sorted(t))
Jayr
quelle