Verwendung von sorted () und sort () in Python
Alle Programmierer müssen irgendwann Code schreiben, um Elemente oder Daten zu sortieren. Das Sortieren kann für die Benutzererfahrung in Ihrer Anwendung von entscheidender Bedeutung sein, unabhängig davon, ob die letzte Aktivität eines Benutzers nach Zeitstempel sortiert oder eine Liste der E-Mail-Empfänger in alphabetischer Reihenfolge nach Nachnamen angezeigt wird. Die Python-Sortierfunktion bietet robuste Funktionen zum einfachen Sortieren oder Anpassen der Bestellung auf granularer Ebene.
In diesem Handbuch erfahren Sie, wie Sie verschiedene Datentypen in verschiedenen Datenstrukturen sortieren, die Reihenfolge anpassen und in Python mit zwei verschiedenen Sortiermethoden arbeiten.
Am Ende dieses Tutorials erfahren Sie, wie Sie:
-
Implementieren Sie die grundlegende Sortierung und Reihenfolge von Python in Datenstrukturen
-
Unterscheiden Sie zwischen
sorted()
und.sort()
-
Passen Sie eine komplexe Sortierreihenfolge in Ihrem Code basierend auf individuellen Anforderungen an
Für dieses Tutorial benötigen Sie ein grundlegendes Verständnis vonlists and tuples sowiesets. Diese Datenstrukturen werden in diesem Lernprogramm verwendet und einige grundlegende Operationen werden an ihnen ausgeführt. Außerdem verwendet dieses Lernprogramm Python 3, sodass die Beispielausgabe in diesem Lernprogramm geringfügig variieren kann, wenn Sie Python 2 verwenden.
Free Bonus:Click here to get access to a chapter from Python Tricks: The Book zeigt Ihnen die Best Practices von Python anhand einfacher Beispiele, die Sie sofort anwenden können, um schöneren + Pythonic-Code zu schreiben.
Bestellwerte mitsorted()
Um mit der Python-Sortierung zu beginnen, erfahren Sie zunächst, wie Sie sowohl numerische Daten als auch Zeichenfolgendaten sortieren.
Nummern sortieren
Sie können Python verwenden, um eine Liste mitsorted()
zu sortieren. In diesem Beispiel wird eine Liste von Ganzzahlen definiert, und dann wirdsorted()
mit der Variablennumbers
als Argument aufgerufen:
>>>
>>> numbers = [6, 9, 3, 1]
>>> sorted(numbers)
[1, 3, 6, 9]
>>> numbers
[6, 9, 3, 1]
Die Ausgabe dieses Codes ist eine neue, sortierte Liste. Wenn die ursprüngliche Variable gedruckt wird, bleiben die Anfangswerte unverändert.
Dieses Beispiel zeigt vier wichtige Merkmale vonsorted()
:
-
Die Funktion
sorted()
musste nicht definiert werden. Es ist eine integrierte Funktion, die in einer Standardinstallation von Python verfügbar ist. -
sorted()
ordnet die Werte innumbers
ohne zusätzliche Argumente oder Parameter in aufsteigender Reihenfolge an, dh vom kleinsten zum größten. -
Die ursprüngliche Variable
numbers
bleibt unverändert, dasorted()
eine sortierte Ausgabe liefert und den ursprünglichen Wert nicht ändert. -
Wenn
sorted()
aufgerufen wird, wird eine geordnete Liste als Rückgabewert bereitgestellt.
Dieser letzte Punkt bedeutet, dasssorted()
für eine Liste verwendet werden kann und die Ausgabe sofort einer Variablen zugewiesen werden kann:
>>>
>>> numbers = [6, 9, 3, 1]
>>> numbers_sorted = sorted(numbers)
>>> numbers_sorted
[1, 3, 6, 9]
>>> numbers
[6, 9, 3, 1]
In diesem Beispiel gibt es jetzt eine neue Variablenumbers_sorted
, die die Ausgabe vonsorted()
gespeichert hat.
Sie können alle diese Beobachtungen bestätigen, indem Siehelp()
aufsorted()
aufrufen. Die optionalen Argumentekey
undreverse
werden später im Lernprogramm behandelt:
>>>
>>> # Python 3
>>> help(sorted)
Help on built-in function sorted in module builtins:
sorted(iterable, /, *, key=None, reverse=False)
Return a new list containing all items from the iterable in ascending order.
A custom key function can be supplied to customize the sort order, and the
reverse flag can be set to request the result in descending order.
Technical Detail: Wenn Sie von Python 2 wechseln und mit der gleichnamigen Funktion vertraut sind, sollten Sie einige wichtige Änderungen in Python 3 kennen:
-
sorted()
von Python 3 hat keinencmp
-Parameter. Stattdessen wird nurkey
verwendet, um eine benutzerdefinierte Sortierlogik einzuführen. -
key
undreverse
müssen im Gegensatz zu Python 2 als Schlüsselwortargumente übergeben werden, wo sie als Positionsargumente übergeben werden können.
Wenn Sie eine Python 2cmp
-Funktion in einekey
-Funktion konvertieren müssen, überprüfen Siefunctools.cmp_to_key()
. Dieses Tutorial behandelt keine Beispiele mit Python 2.
sorted()
kann für Tupel verwendet werden und setzt sehr ähnlich:
>>>
>>> numbers_tuple = (6, 9, 3, 1)
>>> numbers_set = {5, 5, 10, 1, 0}
>>> numbers_tuple_sorted = sorted(numbers_tuple)
>>> numbers_set_sorted = sorted(numbers_set)
>>> numbers_tuple_sorted
[1, 3, 6, 9]
>>> numbers_set_sorted
[0, 1, 5, 10]
Beachten Sie, dass die Ausgabe, obwohl die Eingabe eine Menge und ein Tupel war, eine Liste ist, dasorted()
per Definition eine neue Liste zurückgibt. Das zurückgegebene Objekt kann in einen neuen Typ umgewandelt werden, wenn es mit dem Eingabetyp übereinstimmen muss. Seien Sie vorsichtig, wenn Sie versuchen, die resultierende Liste wieder in eine Menge umzuwandeln, da eine Menge per Definition ungeordnet ist:
>>>
>>> numbers_tuple = (6, 9, 3, 1)
>>> numbers_set = {5, 5, 10, 1, 0}
>>> numbers_tuple_sorted = sorted(numbers_tuple)
>>> numbers_set_sorted = sorted(numbers_set)
>>> numbers_tuple_sorted
[1, 3, 6, 9]
>>> numbers_set_sorted
[0, 1, 5, 10]
>>> tuple(numbers_tuple_sorted)
(1, 3, 6, 9)
>>> set(numbers_set_sorted)
{0, 1, 10, 5}
Der Wert vonnumbers_set_sorted
bei Umwandlung inset
wird nicht wie erwartet geordnet. Die andere Variable,numbers_tuple_sorted
, behielt die sortierte Reihenfolge bei.
Zeichenfolgen sortieren
str
Typen sortieren ähnlich wie andere iterable, wie Liste und Tupel. Das folgende Beispiel zeigt, wiesorted()
jedes Zeichen in dem übergebenen Wert durchläuft und sie in der Ausgabe anordnet:
>>>
>>> string_number_value = '34521'
>>> string_value = 'I like to sort'
>>> sorted_string_number = sorted(string_number_value)
>>> sorted_string = sorted(string_value)
>>> sorted_string_number
['1', '2', '3', '4', '5']
>>> sorted_string
[' ', ' ', ' ', 'I', 'e', 'i', 'k', 'l', 'o', 'o', 'r', 's', 't', 't']
sorted()
behandeltstr
wie eine Liste und durchläuft jedes Element. Instr
bedeutet jedes Element jedes Zeichen instr
. sorted()
behandelt einen Satz nicht anders und sortiert jedes Zeichen, einschließlich Leerzeichen.
.split()
kann dieses Verhalten ändern und die Ausgabe bereinigen, und.join()
kann alles wieder zusammensetzen. Wir werden in Kürze die spezifische Reihenfolge der Ausgabe behandeln und erklären, warum dies so ist:
>>>
>>> string_value = 'I like to sort'
>>> sorted_string = sorted(string_value.split())
>>> sorted_string
['I', 'like', 'sort', 'to']
>>> ' '.join(sorted_string)
'I like sort to'
Der ursprüngliche Satz in diesem Beispiel wird in eine Liste von Wörtern konvertiert, anstatt ihn alsstr
zu belassen. Diese Liste wird dann sortiert und kombiniert, um anstelle einer Liste wieder einstr
zu bilden.
Einschränkungen und Fallstricke bei der Python-Sortierung
Beachten Sie einige Einschränkungen und merkwürdige Verhaltensweisen, die auftreten können, wenn Sie Python zum Sortieren von Werten neben Ganzzahlen verwenden.
Listen mit nicht vergleichbaren Datentypen dürfen nichtsorted()
ein
Es gibt Datentypen, die nicht mit nursorted()
miteinander verglichen werden können, da sie zu unterschiedlich sind. Python gibt einen Fehler zurück, wenn Sie versuchen,sorted()
in einer Liste mit nicht vergleichbaren Daten zu verwenden. In diesem Beispiel könnenNone
undint
in derselben Liste aufgrund ihrer Inkompatibilität nicht sortiert werden:
>>>
>>> mixed_types = [None, 0]
>>> sorted(mixed_types)
Traceback (most recent call last):
File "", line 1, in
TypeError: '<' not supported between instances of 'int' and 'NoneType'
Dieser Fehler zeigt, warum Python die ihm zugewiesenen Werte nicht sortieren kann. Es wird versucht, die Werte zu ordnen, indem der Operator kleiner als (<
) verwendet wird, um zu bestimmen, welcher Wert in der Sortierreihenfolge niedriger ist. Sie können diesen Fehler replizieren, indem Sie die beiden Werte manuell vergleichen:
>>>
>>> None < 0
Traceback (most recent call last):
File "", line 1, in
TypeError: '<' not supported between instances of 'NoneType' and 'int'
Das gleicheTypeError
wird ausgelöst, wenn Sie versuchen, zwei nicht vergleichbare Werte zu vergleichen, ohnesorted()
zu verwenden.
Wenn die Werte in der Liste verglichen werden können und keineTypeError
auslösen, kann die Liste sortiert werden. Dies verhindert, dass iterable Elemente mit an sich ungeordneten Werten sortiert werden und eine Ausgabe erzeugt wird, die möglicherweise keinen Sinn ergibt.
Sollte beispielsweise die Zahl1
vor dem Wortapple
tehen? Wenn eine Iterable jedoch eine Kombination aus Ganzzahlen und Zeichenfolgen enthält, die alle Zahlen sind, können sie mithilfe eines Listenverständnisses in vergleichbare Datentypen umgewandelt werden:
>>>
>>> mixed_numbers = [5, "1", 100, "34"]
>>> sorted(mixed_numbers)
Traceback (most recent call last):
File "", line 1, in
TypeError: '<' not supported between instances of 'str' and 'int'
>>> # List comprehension to convert all values to integers
>>> [int(x) for x in mixed_numbers]
[5, 1, 100, 34]
>>> sorted([int(x) for x in mixed_numbers])
[1, 5, 34, 100]
Für jedes Element inmixed_numbers
wirdint()
aufgerufen, um allestr
-Werte inint
-Werte umzuwandeln. sorted()
wird dann aufgerufen und kann jedes Element erfolgreich vergleichen und eine sortierte Ausgabe bereitstellen.
Python kann einen Wert auch implizit in einen anderen Typ konvertieren. Im folgenden Beispiel ist die Bewertung von1 <= 0
eine falsche Aussage, sodass die Ausgabe der BewertungFalse
ist. Die Anzahl1
kann alsbool
-Typ inTrue
konvertiert werden, während0
inFalse
konvertiert wird.
Obwohl die Elemente in der Liste unterschiedlich aussehen, können sie alle in Boolesche Werte (True
oderFalse
) konvertiert und mitsorted()
miteinander verglichen werden:
>>>
>>> similar_values = [False, 0, 1, 'A' == 'B', 1 <= 0]
>>> sorted(similar_values)
[False, 0, False, False, 1]
'A' == 'B'
und1 <= 0
werden inFalse
konvertiert und in der geordneten Ausgabe zurückgegeben.
Dieses Beispiel zeigt einen wichtigen Aspekt der Sortierung:sort stability. Wenn Sie in Python gleiche Werte sortieren, behalten diese ihre ursprüngliche Reihenfolge in der Ausgabe bei. Obwohl sich die1
verschoben haben, sind alle anderen Werte gleich, sodass sie ihre ursprüngliche Reihenfolge relativ zueinander beibehalten. Im folgenden Beispiel werden alle Werte als gleich angesehen und behalten ihre ursprüngliche Position bei:
>>>
>>> false_values = [False, 0, 0, 1 == 2, 0, False, False]
>>> sorted(false_values)
[False, 0, 0, False, 0, False, False]
Wenn Sie die ursprüngliche Reihenfolge und die sortierte Ausgabe überprüfen, werden Sie feststellen, dass1 == 2
inFalse
konvertiert wird und alle sortierten Ausgaben in der ursprünglichen Reihenfolge vorliegen.
Wenn Sie Zeichenfolgen sortieren, ist der Fall wichtig
sorted()
kann für eine Liste von Zeichenfolgen verwendet werden, um die Werte in aufsteigender Reihenfolge zu sortieren, die standardmäßig alphabetisch zu sein scheint:
>>>
>>> names = ['Harry', 'Suzy', 'Al', 'Mark']
>>> sorted(names)
['Al', 'Harry', 'Mark', 'Suzy']
Python verwendet jedoch dieUnicode Code Point des ersten Buchstabens in jeder Zeichenfolge, um die aufsteigende Sortierreihenfolge zu bestimmen. Das bedeutet, dasssorted()
die NamenAl
undal
nicht gleich behandeln werden. In diesem Beispiel wirdord()
verwendet, um den Unicode-Codepunkt des ersten Buchstabens in jeder Zeichenfolge zurückzugeben:
>>>
>>> names_with_case = ['harry', 'Suzy', 'al', 'Mark']
>>> sorted(names_with_case)
['Mark', 'Suzy', 'al', 'harry']
>>> # List comprehension for Unicode Code Point of first letter in each word
>>> [(ord(name[0]), name[0]) for name in sorted(names_with_case)]
[(77, 'M'), (83, 'S'), (97, 'a'), (104, 'h')]
name[0]
gibt das erste Zeichen in jedem Element vonsorted(names_with_case)
zurück, undord()
liefert den Unicode-Codepunkt. Obwohla
im Alphabet vorM
steht, steht der Codepunkt fürM
vora
, sodass die sortierte Ausgabe zuerstM
enthält.
Wenn der erste Buchstabe derselbe ist, verwendetsorted()
das zweite Zeichen, um die Reihenfolge zu bestimmen, und das dritte Zeichen, wenn dies gleich ist, und so weiter bis zum Ende der Zeichenfolge:
>>>
>>> very_similar_strs = ['hhhhhd', 'hhhhha', 'hhhhhc','hhhhhb']
>>> sorted(very_similar_strs)
['hhhhha', 'hhhhhb', 'hhhhhc', 'hhhhhd']
Jeder Wert vonvery_similar_strs
ist bis auf das letzte Zeichen identisch. sorted()
vergleicht die Zeichenfolgen. Da die ersten fünf Zeichen identisch sind, basiert die Ausgabe auf dem sechsten Zeichen.
Zeichenfolgen mit identischen Werten werden am kürzesten bis am längsten sortiert, da die kürzeren Zeichenfolgen keine Elemente enthalten, mit denen sie mit den längeren Zeichenfolgen verglichen werden können:
>>>
>>> different_lengths = ['hhhh', 'hh', 'hhhhh','h']
>>> sorted(different_lengths)
['h', 'hh', 'hhhh', 'hhhhh']
Die kürzeste Zeichenfolgeh
wird zuerst geordnet, die längstehhhhh
zuletzt.
Verwenden vonsorted()
Mit einemreverse
-Argument
Wie in der Dokumentation zuhelp()
fürsorted()
gezeigt, gibt es ein optionales Schlüsselwortargument namensreverse
, das das Sortierverhalten basierend auf dem ihm zugewiesenen Booleschen Wert ändert. Wennreverse
True
zugewiesen ist, erfolgt die Sortierung in absteigender Reihenfolge:
>>>
>>> names = ['Harry', 'Suzy', 'Al', 'Mark']
>>> sorted(names)
['Al', 'Harry', 'Mark', 'Suzy']
>>> sorted(names, reverse=True)
['Suzy', 'Mark', 'Harry', 'Al']
Die Sortierlogik bleibt gleich, was bedeutet, dass die Namen immer noch nach ihrem Anfangsbuchstaben sortiert werden. Die Ausgabe wurde jedoch mit dem Schlüsselwortreverse
aufTrue
umgekehrt.
WennFalse
zugewiesen ist, bleibt die Reihenfolge aufsteigend. Jedes der vorherigen Beispiele kann verwendet werden, um das Verhalten der Umkehrung unter Verwendung vonTrue
oderFalse
zu sehen:
>>>
>>> names_with_case = ['harry', 'Suzy', 'al', 'Mark']
>>> sorted(names_with_case, reverse=True)
['harry', 'al', 'Suzy', 'Mark']
>>> similar_values = [False, 1, 'A' == 'B', 1 <= 0]
>>> sorted(similar_values, reverse=True)
[1, False, False, False]
>>> numbers = [6, 9, 3, 1]
>>> sorted(numbers, reverse=False)
[1, 3, 6, 9]
sorted()
Mit einemkey
Argument
Eine der mächtigsten Komponenten vonsorted()
ist das Schlüsselwortargumentkey
. Dieses Argument erwartet, dass eine Funktion an sie übergeben wird, und diese Funktion wird für jeden Wert in der Liste verwendet, der sortiert wird, um die resultierende Reihenfolge zu bestimmen.
Nehmen wir zur Veranschaulichung eines grundlegenden Beispiels an, dass für die Bestellung einer bestimmten Liste die Länge der Zeichenfolgen in der Liste vom kürzesten zum längsten erforderlich ist. Die Funktion zum Zurückgeben der Länge eines Strings,len()
, wird mit dem Argumentkey
verwendet:
>>>
>>> word = 'paper'
>>> len(word)
5
>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=len)
['pie', 'book', 'banana', 'Washington']
Die resultierende Reihenfolge ist eine Liste mit einer Zeichenfolgenreihenfolge von kürzester bis längster. Die Länge jedes Elements in der Liste wird durchlen()
bestimmt und dann in aufsteigender Reihenfolge zurückgegeben.
Kehren wir zum früheren Beispiel der Sortierung nach Anfangsbuchstaben zurück, wenn der Fall anders ist. key
kann verwendet werden, um dieses Problem zu lösen, indem die gesamte Zeichenfolge in Kleinbuchstaben konvertiert wird:
>>>
>>> names_with_case = ['harry', 'Suzy', 'al', 'Mark']
>>> sorted(names_with_case)
['Mark', 'Suzy', 'al', 'harry']
>>> sorted(names_with_case, key=str.lower)
['al', 'harry', 'Mark', 'Suzy']
Die Ausgabewerte wurden nicht in Kleinbuchstaben konvertiert, dakey
die Daten in der ursprünglichen Liste nicht manipuliert. Während des Sortierens wird die ankey
übergebene Funktion für jedes Element aufgerufen, um die Sortierreihenfolge zu bestimmen. Die ursprünglichen Werte werden jedoch in der Ausgabe angezeigt.
Es gibt zwei Haupteinschränkungen, wenn Sie Funktionen mit dem Argumentkey
verwenden.
Erstens muss die Anzahl der erforderlichen Argumente in der ankey
übergebenen Funktion eins sein.
Das folgende Beispiel zeigt die Definition einer Additionsfunktion, die zwei Argumente akzeptiert. Wenn diese Funktion inkey
in einer Liste von Zahlen verwendet wird, schlägt sie fehl, weil ein zweites Argument fehlt. Jedes Mal, wennadd()
während der Sortierung aufgerufen wird, empfängt es jeweils nur ein Element aus der Liste:
>>>
>>> def add(x, y):
... return x + y
...
>>> values_to_add = [1, 2, 3]
>>> sorted(values_to_add, key=add)
Traceback (most recent call last):
File "", line 1, in
TypeError: add() missing 1 required positional argument: 'y'
Die zweite Einschränkung besteht darin, dass die mitkey
verwendete Funktion alle Werte in der Iterable verarbeiten kann. Beispielsweise haben Sie eine Liste von Zahlen, die als Zeichenfolgen dargestellt werden, die insorted()
verwendet werden sollen, undkey
wird versuchen, sie mitint
in Zahlen umzuwandeln. Wenn ein Wert in der Iterable nicht in eine Ganzzahl umgewandelt werden kann, schlägt die Funktion fehl:
>>>
>>> values_to_cast = ['1', '2', '3', 'four']
>>> sorted(values_to_cast, key=int)
Traceback (most recent call last):
File "", line 1, in
ValueError: invalid literal for int() with base 10: 'four'
Jeder numerische Wert alsstr
kann inint
konvertiert werden,four
jedoch nicht. Dies führt dazu, dass einValueError
ausgelöst wird und erklärt wird, dassfour
nicht inint
konvertiert werden kann, da es ungültig ist.
Die Funktionalität vonkey
ist äußerst leistungsfähig, da fast jede integrierte oder benutzerdefinierte Funktion zum Bearbeiten der Ausgabereihenfolge verwendet werden kann.
Wenn die Bestellanforderung darin besteht, eine Iterierbarkeit nach dem letzten Buchstaben in jeder Zeichenfolge zu bestellen (und wenn der Buchstabe derselbe ist, dann den nächsten Buchstaben zu verwenden), kann einfunction definiert und dann bei der Sortierung verwendet werden. Das folgende Beispiel definiert eine Funktion, die die an sie übergebene Zeichenfolge umkehrt, und diese Funktion wird dann als Argument fürkey
verwendet:
>>>
>>> def reverse_word(word):
... return word[::-1]
...
>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=reverse_word)
['banana', 'pie', 'book', 'Washington']
Die Slice-Syntax vonword[::-1]
wird verwendet, um eine Zeichenfolge umzukehren. Auf jedes Element wirdreverse_word()
angewendet, und die Sortierreihenfolge basiert auf den Zeichen im Rückwärtswort.
Anstatt eine eigenständige Funktion zu schreiben, können Sie einelambda
-Funktion verwenden, die im Argumentkey
definiert ist.
Alambda
ist eine anonyme Funktion, die:
-
Muss inline definiert werden
-
Hat keinen Namen
-
Kann keinestatements enthalten
-
Wird wie eine Funktion ausgeführt
Im folgenden Beispiel istkey
alslambda
ohne Namen definiert, das Argument vonlambda
istx
undx[::-1]
ist die Operation das wird mit dem Argument durchgeführt:
>>>
>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=lambda x: x[::-1])
['banana', 'pie', 'book', 'Washington']
x[::-1]
wird für jedes Element aufgerufen und kehrt das Wort um. Diese umgekehrte Ausgabe wird dann zum Sortieren verwendet, aber die ursprünglichen Wörter werden immer noch zurückgegeben.
Wenn sich die Anforderung ändert und die Reihenfolge ebenfalls umgekehrt werden sollte, kann das Schlüsselwortreverse
neben dem Argumentkey
verwendet werden:
>>>
>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=lambda x: x[::-1], reverse=True)
['Washington', 'book', 'pie', 'banana']
Die Funktionen vonlambda
ind auch nützlich, wenn Sieclass
Objekte basierend auf einer Eigenschaft sortieren müssen. Wenn Sie eine Gruppe von Schülern haben und diese nach ihrer höchsten bis niedrigsten Abschlussnote sortieren müssen, können Sie mitlambda
die Eigenschaftgrade
ausclass
abrufen:
>>>
>>> from collections import namedtuple
>>> StudentFinal = namedtuple('StudentFinal', 'name grade')
>>> bill = StudentFinal('Bill', 90)
>>> patty = StudentFinal('Patty', 94)
>>> bart = StudentFinal('Bart', 89)
>>> students = [bill, patty, bart]
>>> sorted(students, key=lambda x: getattr(x, 'grade'), reverse=True)
[StudentFinal(name='Patty', grade=94), StudentFinal(name='Bill', grade=90), StudentFinal(name='Bart', grade=89)]
In diesem Beispiel werdennamedtuple
verwendet, um Klassen mit den Attributenname
undgrade
zu erstellen. lambda
ruft für jedes Elementgetattr()
auf und gibt den Wert fürgrade
zurück.
reverse
wird aufTrue
gesetzt, damit die aufsteigende Ausgabe absteigend gespiegelt wird, sodass die höchsten Noten zuerst geordnet werden.
Es gibt unendlich viele Möglichkeiten, wie Sie bestellen können, wenn Sie die Schlüsselwortargumentekey
undreverse
fürsorted()
verwenden. Code kann sauber und kurz gehalten werden, wenn Sie ein einfacheslambda
für eine kleine Funktion verwenden, oder Sie können eine ganz neue Funktion schreiben, importieren und im Schlüsselargument verwenden.
Bestellwerte mit.sort()
Das sehr ähnlich benannte.sort()
unterscheidet sich erheblich von dem eingebautensorted()
. Sie erreichen mehr oder weniger dasselbe, aber diehelp()
-Dokumentation fürlist.sort()
zeigt zwei der kritischsten Unterschiede zwischen.sort()
undsorted()
auf:
>>>
>>> # Python2
Help on method_descriptor:
sort(...)
L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
cmp(x, y) -> -1, 0, 1
>>> # Python3
>>> help(list.sort)
Help on method_descriptor:
sort(...)
L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*
Erstens ist sort eine Methode der Klasselist
und kann nur mit Listen verwendet werden. Es ist kein eingebautes Element, an das eine Iteration übergeben wird.
Zweitens gibt.sort()
None
zurück und ändert die vorhandenen Werte. Werfen wir einen Blick auf die Auswirkungen dieser beiden Unterschiede im Code:
>>>
>>> values_to_sort = [5, 2, 6, 1]
>>> # Try to call .sort() like sorted()
>>> sort(values_to_sort)
Traceback (most recent call last):
File "", line 1, in
NameError: name 'sort' is not defined
>>> # Try to use .sort() on a tuple
>>> tuple_val = (5, 1, 3, 5)
>>> tuple_val.sort()
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'tuple' object has no attribute 'sort'
>>> # Sort the list and assign to new variable
>>> sorted_values = values_to_sort.sort()
>>> print(sorted_values)
None
>>> # Print original variable
>>> print(values_to_sort)
[1, 2, 5, 6]
In diesem Codebeispiel gibt es einige ziemlich dramatische Unterschiede in der Funktionsweise von.sort()
im Vergleich zusorted()
:
-
Es gibt keine geordnete Ausgabe von
.sort()
, daher übergibt die Zuordnung zu einer neuen Variablen nur den TypNone
. -
Die
values_to_sort
-Liste wurde geändert, und die ursprüngliche Reihenfolge wird in keiner Weise beibehalten.
Diese Verhaltensunterschiede machen.sort()
undsorted()
im Code absolut nicht austauschbar und können zu völlig unerwarteten Ergebnissen führen, wenn man sie falsch verwendet.
.sort()
hat dieselben optionalen Schlüsselwortargumentekey
undreverse
, die dieselbe robuste Funktionalität wiesorted()
erzeugen. Hier können Sie eine Liste von Phrasen nach dem zweiten Buchstaben des dritten Wortes sortieren und die Liste in umgekehrter Reihenfolge zurückgeben:
>>>
>>> phrases = ['when in rome',
... 'what goes around comes around',
... 'all is fair in love and war'
... ]
>>> phrases.sort(key=lambda x: x.split()[2][1], reverse=True)
>>> phrases
['what goes around comes around', 'when in rome', 'all is fair in love and war']
In diesem Beispiel wird einlambda
verwendet, um Folgendes zu tun:
-
Teilen Sie jede Phrase in eine Liste von Wörtern
-
Suchen Sie das dritte Element oder Wort in diesem Fall
-
Finden Sie den zweiten Buchstaben in diesem Wort
Wann werdensorted()
und wann.sort()
verwendet?
Sie haben die Unterschiede zwischensorted()
und.sort()
gesehen, aber wann verwenden Sie welche?
Nehmen wir an, es steht ein 5-km-Rennen an: Das erste jährliche Python-5-km-Rennen. Die Daten aus dem Rennen müssen erfasst und sortiert werden. Die Daten, die erfasst werden müssen, sind die Startnummer des Läufers und die Anzahl der Sekunden, die zum Beenden des Rennens benötigt wurden:
>>>
>>> from collections import namedtuple
>>> Runner = namedtuple('Runner', 'bibnumber duration')
Wenn die Läufer die Ziellinie überqueren, wird jedesRunner
zu einer Liste mit dem Namenrunners
hinzugefügt. Bei 5-km-Rennen überqueren nicht alle Läufer gleichzeitig die Startlinie, sodass die erste Person, die die Ziellinie überquert, möglicherweise nicht die schnellste Person ist:
>>>
>>> runners = []
>>> runners.append(Runner('2528567', 1500))
>>> runners.append(Runner('7575234', 1420))
>>> runners.append(Runner('2666234', 1600))
>>> runners.append(Runner('2425234', 1490))
>>> runners.append(Runner('1235234', 1620))
>>> # Thousands and Thousands of entries later...
>>> runners.append(Runner('2526674', 1906))
Jedes Mal, wenn ein Läufer die Ziellinie überquert, werden seine Startnummer und seine Gesamtdauer in Sekunden zurunners
addiert.
Jetzt sieht der pflichtbewusste Programmierer, der für die Verarbeitung der Ergebnisdaten verantwortlich ist, diese Liste, weiß, dass die fünf schnellsten Teilnehmer die Gewinner sind, die Preise erhalten, und die verbleibenden Läufer werden nach der schnellsten Zeit sortiert.
Es gibt keine Anforderungen für mehrere Arten der Sortierung nach verschiedenen Attributen. Die Liste hat eine angemessene Größe. Es wird nicht erwähnt, dass die Liste irgendwo gespeichert wird. Sortieren Sie einfach nach Dauer und holen Sie sich die fünf Teilnehmer mit der niedrigsten Dauer:
>>>
>>> runners.sort(key=lambda x: getattr(x, 'duration'))
>>> top_five_runners = runners[:5]
Der Programmierer verwendetlambda
im Argumentkey
, um das Attributduration
von jedem Läufer abzurufen undrunners
mit.sort()
zu sortieren. Nachdemrunners
sortiert wurde, werden die ersten 5 Elemente intop_five_runners
gespeichert.
Mission erfüllt! Der Rennleiter kommt vorbei und informiert den Programmierer, dass er seit der aktuellen Version von Python 3.7 entschieden hat, dass jede siebenunddreißigste Person, die die Ziellinie überquert hat, eine kostenlose Sporttasche bekommt.
Zu diesem Zeitpunkt beginnt der Programmierer zu schwitzen, da die Liste der Läufer irreversibel geändert wurde. Es gibt keine Möglichkeit, die ursprüngliche Liste der Läufer in der Reihenfolge wiederherzustellen, in der sie fertig sind, und jede siebenunddreißigste Person zu finden.
Wenn Sie mit wichtigen Daten arbeiten und sogar die Möglichkeit besteht, dass die Originaldaten wiederhergestellt werden müssen, ist.sort()
nicht die beste Option. Wenn es sich bei den Daten um eine Kopie handelt, wenn es sich um unwichtige Arbeitsdaten handelt oder wenn es niemandem etwas ausmacht, sie zu verlieren, weil sie abgerufen werden können, kann.sort()
eine gute Option sein.
Alternativ könnten die Läufer mitsorted()
und mit denselbenlambda
sortiert worden sein:
>>>
>>> runners_by_duration = sorted(runners, key=lambda x: getattr(x, 'duration'))
>>> top_five_runners = runners_by_duration[:5]
In diesem Szenario mitsorted()
ist die ursprüngliche Liste der Läufer noch intakt und wurde nicht überschrieben. Die spontane Anforderung, jede siebenunddreißigste Person zum Überqueren der Ziellinie zu finden, kann durch Interaktion mit den ursprünglichen Werten erreicht werden:
>>>
>>> every_thirtyseventh_runners = runners[::37]
every_thirtyseventh_runners
wird mithilfe eines Schrittes in der Listen-Slice-Syntax fürrunners
erstellt, der noch die ursprüngliche Reihenfolge enthält, in der die Läufer die Ziellinie überquert haben.
So sortieren Sie in Python: Fazit
.sort()
undsorted()
können genau die Sortierreihenfolge bereitstellen, die Sie benötigen, wenn Sie sie ordnungsgemäß mit den optionalen Schlüsselwortargumentenreverse
undkey
verwenden.
Beide haben sehr unterschiedliche Eigenschaften in Bezug auf Ausgabe und direkte Änderungen. Denken Sie also über alle Anwendungsfunktionen oder -programme nach, die.sort()
verwenden, da sie Daten unwiderruflich überschreiben können.
Versuchen Sie für begeisterte Pythonisten, die eine Herausforderung beim Sortieren suchen, komplexere Datentypen beim Sortieren zu verwenden: verschachtelte iterable. Sie können auch in die Open-Source-Python-Code-Implementierungen für die integrierten Funktionen eintauchen und sich über den in Python verwendeten Sortieralgorithmus namensTimsort informieren.