Was ist der Unterschied zwischen "sortiert (Liste)" und "list.sort ()"?

194

list.sort()sortiert die Liste und ersetzt die ursprüngliche Liste, während sorted(list)eine sortierte Kopie der Liste zurückgegeben wird, ohne die ursprüngliche Liste zu ändern.

  • Wann wird einer dem anderen vorgezogen?
  • Welches ist effizienter? Um wie viel?
  • Kann eine Liste nach der Ausführung in den unsortierten Zustand zurückgesetzt werden list.sort()?
Alvas
quelle
4
Passen Sie auf, wenn Sie (versehentlich) sorted()ein Zeichenfolgenargument aufrufen, aber denken, dass es eine Liste ist, erhalten Sie ein Listenergebnis, keine Zeichenfolge : sorted("abcd", reverse=True)gibt ['d', 'c', 'b', 'a']nicht"dcba"
smci

Antworten:

316

sorted()Gibt eine neue sortierte Liste zurück, wobei die ursprüngliche Liste nicht betroffen ist. list.sort()sortiert die Liste in-Place , die Listenindizes mutiert und kehrt None(wie alle in-Place - Operationen).

sorted()funktioniert auf jeder iterierbaren, nicht nur auf Listen. Zeichenfolgen, Tupel, Wörterbücher (Sie erhalten die Schlüssel), Generatoren usw. geben eine Liste mit allen Elementen zurück, sortiert.

  • Verwenden list.sort()Sie diese Option, sorted()wenn Sie die Liste mutieren möchten, wenn Sie ein neues sortiertes Objekt zurückhaben möchten. Verwenden sorted()Sie diese Option, wenn Sie etwas sortieren möchten, das iterierbar und noch keine Liste ist .

  • Für Listen list.sort()ist schneller als sorted()weil es keine Kopie erstellen muss. Für jedes andere iterable haben Sie keine Wahl.

  • Nein, Sie können die ursprünglichen Positionen nicht abrufen. Sobald Sie angerufen haben, ist list.sort()die ursprüngliche Bestellung weg.

Martijn Pieters
quelle
6
Wenn eine Python-Funktion zurückgegeben wird None, ist dies im Allgemeinen ein Zeichen dafür, dass die Vorgänge ordnungsgemäß ausgeführt wurden. Wenn Sie sie drucken möchten, wird im Allgemeinen list.sort()None zurückgegeben.
user1767754
44

Was ist der Unterschied zwischen sorted(list)vs list.sort()?

  • list.sort mutiert die Liste an Ort und Stelle und kehrt zurück None
  • sorted Nimmt eine beliebige iterable & gibt eine neue Liste zurück, sortiert.

sorted entspricht dieser Python-Implementierung, aber die in CPython integrierte Funktion sollte messbar schneller ausgeführt werden, da sie in C geschrieben ist:

def sorted(iterable, key=None):
    new_list = list(iterable)    # make a new list
    new_list.sort(key=key)       # sort it
    return new_list              # return it

wann welche verwenden?

  • Verwenden list.sort Sie diese wenn Sie die ursprüngliche Sortierreihenfolge nicht beibehalten möchten (damit Sie die Liste direkt im Speicher wiederverwenden können) und wenn Sie der alleinige Eigentümer der Liste sind (wenn die Liste von einem anderen Code gemeinsam genutzt wird und Sie mutieren Sie es, Sie könnten Fehler einführen, wo diese Liste verwendet wird.)
  • Verwenden sortedSie diese Option, wenn Sie die ursprüngliche Sortierreihenfolge beibehalten oder eine neue Liste erstellen möchten, die nur Ihrem lokalen Code gehört.

Können die ursprünglichen Positionen einer Liste nach list.sort () abgerufen werden?

Nein - wenn Sie nicht selbst eine Kopie erstellt haben, gehen diese Informationen verloren, da die Sortierung an Ort und Stelle erfolgt.

"Und was ist schneller? Und wie viel schneller?"

Verwenden Sie das timeit-Modul, um die Nachteile beim Erstellen einer neuen Liste zu veranschaulichen. Hier ist unser Setup:

import timeit
setup = """
import random
lists = [list(range(10000)) for _ in range(1000)]  # list of lists
for l in lists:
    random.shuffle(l) # shuffle each list
shuffled_iter = iter(lists) # wrap as iterator so next() yields one at a time
"""

Und hier sind unsere Ergebnisse für eine Liste zufällig angeordneter 10000 Ganzzahlen. Wie wir hier sehen können, haben wir einen älteren Mythos der Kosten für die Erstellung von Listen widerlegt :

Python 2.7

>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[3.75168503401801, 3.7473005310166627, 3.753129180986434]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[3.702025591977872, 3.709248117986135, 3.71071034099441]

Python 3

>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[2.797430992126465, 2.796825885772705, 2.7744789123535156]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[2.675589084625244, 2.8019039630889893, 2.849375009536743]

Nach einigen Rückmeldungen entschied ich, dass ein weiterer Test mit unterschiedlichen Eigenschaften wünschenswert wäre. Hier stelle ich die gleiche zufällig angeordnete Liste mit einer Länge von 100.000 für jede Iteration 1000 Mal zur Verfügung.

import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""

Ich interpretiere den Unterschied dieser größeren Sorte, der sich aus dem von Martijn erwähnten Kopieren ergibt, aber er dominiert nicht bis zu dem Punkt, der in der älteren, populäreren Antwort hier angegeben ist, hier beträgt die Zeitzunahme nur etwa 10%

>>> timeit.repeat("lst[:].sort()", setup=setup, number = 10000)
[572.919036605, 573.1384446719999, 568.5923951]
>>> timeit.repeat("sorted(lst[:])", setup=setup, number = 10000)
[647.0584738299999, 653.4040515829997, 657.9457361929999]

Ich habe das oben genannte auch auf einer viel kleineren Sorte ausgeführt und festgestellt, dass die neue sortedKopierversion bei einer Länge von 1000 noch etwa 2% länger dauert.

Poke hat auch seinen eigenen Code ausgeführt. Hier ist der Code:

setup = '''
import random
random.seed(12122353453462456)
lst = list(range({length}))
random.shuffle(lst)
lists = [lst[:] for _ in range({repeats})]
it = iter(lists)
'''
t1 = 'l = next(it); l.sort()'
t2 = 'l = next(it); sorted(l)'
length = 10 ** 7
repeats = 10 ** 2
print(length, repeats)
for t in t1, t2:
    print(t)
    print(timeit(t, setup=setup.format(length=length, repeats=repeats), number=repeats))

Er fand für 1000000 Längensortierung (100-mal ausgeführt) ein ähnliches Ergebnis, aber nur etwa 5% mehr Zeit, hier ist die Ausgabe:

10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655

Fazit:

Eine große Liste, die beim sortedErstellen einer Kopie sortiert wird, dominiert wahrscheinlich die Unterschiede, aber die Sortierung selbst dominiert den Vorgang, und das Organisieren Ihres Codes um diese Unterschiede herum wäre eine vorzeitige Optimierung. Ich würde verwenden, sortedwenn ich eine neue sortierte Liste der Daten benötige, und ich würde verwenden, list.sortwenn ich eine Liste direkt sortieren muss, und dies meine Verwendung bestimmen lassen.

Aaron Hall
quelle
4
Das Generator-Setup ist nett, aber ich würde nicht den Schluss ziehen, dass Sie einen Mythos zu schnell zerstört haben. Es bleibt die Tatsache, dass sorted()ein neues Listenobjekt zugewiesen und die Referenzen kopiert werden müssen. Die restlichen Codepfade sind identisch. Überprüfen Sie, ob Sie dieselben Tests mit größeren Listen ausführen können. Vergleichen Sie es mit dem Erstellen von Kopien von Listen und prüfen Sie, ob Sie die gefundenen Unterschiede usw. replizieren können.
Martijn Pieters
11

Der Hauptunterschied besteht darin, dass sorted(some_list)ein neues zurückgegeben wirdlist :

a = [3, 2, 1]
print sorted(a) # new list
print a         # is not modified

und some_list.sort(), sortiert die Liste an Ort und Stelle :

a = [3, 2, 1]
print a.sort() # in place
print a         # it's modified

Beachten Sie, dass, da a.sort()nichts zurückgegeben print a.sort()wird, gedruckt wird None.


Kann eine Liste der ursprünglichen Positionen nach list.sort () abgerufen werden?

Nein, da dadurch die ursprüngliche Liste geändert wird.

Christian
quelle
1
print a.sort()druckt nichts.
Burhan Khalid
1
Es wird gedruckt None, das werde ich klarstellen.
Christian
1

Die Funktion .sort () speichert den Wert der neuen Liste direkt in der Listenvariablen. Die Antwort auf Ihre dritte Frage wäre NEIN. Auch wenn Sie dies mit sortiert (Liste) tun, können Sie es verwenden, da es nicht in der Listenvariablen gespeichert ist. Manchmal fungiert die Methode .sort () auch als Funktion oder sagt, dass sie Argumente enthält.

Sie müssen den Wert von sortiert (Liste) explizit in einer Variablen speichern.

Auch bei kurzer Datenverarbeitung spielt die Geschwindigkeit keine Rolle. aber für lange Listen; Sie sollten die .sort () -Methode direkt verwenden, um schnell arbeiten zu können. Aber auch hier werden Sie irreversiblen Handlungen ausgesetzt sein.

Vicrobot
quelle
"Die Funktion .sort () speichert den Wert der neuen Liste direkt in der Listenvariablen" Huh? Welche neue Liste? Es gibt keine neue Liste. Die list.sort()Methode sortiert das Listenobjekt direkt.
PM 2Ring
Was soll das auch bedeuten? "Manchmal fungiert die Methode .sort () als Funktion oder sagt, dass sie Argumente enthält."
PM 2Ring
Was ich unter neuer Liste verstehe, ist die geänderte Liste, und .sort () speichert diese geänderte Liste nur in derselben Variablen.
Vicrobot
Ja, absolut manchmal .sort()nimmt die Methode Argumente und fungiert als Funktion. Wir nennen es auch Methode, weil es ein Attribut des Listendatentyps ist.
Vicrobot
Wenn mein Konzept einen Fehler enthält, sagen Sie mir, ich werde danach suchen und meine Konzepte sowie meine Antwort verbessern. Vielen Dank
Vicrobot
1

Hier sind einige einfache Beispiele, um den Unterschied in der Aktion zu sehen:

Siehe die Liste der Nummern hier:

nums = [1, 9, -3, 4, 8, 5, 7, 14]

Wenn Sie sorteddiese Liste aufrufen , sortedwird eine Kopie der Liste erstellt. (Das heißt, Ihre ursprüngliche Liste bleibt unverändert.)

Mal schauen.

sorted(nums)

kehrt zurück

[-3, 1, 4, 5, 7, 8, 9, 14]

Mit Blick auf die numswieder

nums

Wir sehen die ursprüngliche Liste (unverändert und NICHT sortiert). sortedhat die ursprüngliche Liste nicht geändert

[1, 2, -3, 4, 8, 5, 7, 14]

Wenn Sie dieselbe numsListe verwenden und die sortFunktion darauf anwenden , wird die tatsächliche Liste geändert.

Mal schauen.

Beginnen Sie mit unserer numsListe, um sicherzustellen, dass der Inhalt immer noch der gleiche ist.

nums

[-3, 1, 4, 5, 7, 8, 9, 14]

nums.sort()

Jetzt wird die ursprüngliche Nummernliste geändert und wenn wir uns die Nummern ansehen, sehen wir, dass sich unsere ursprüngliche Liste geändert hat und jetzt sortiert ist.

nums
[-3, 1, 2, 4, 5, 7, 8, 14]
Stryker
quelle
Vielen Dank, dass Sie das Original und die Kopie ausführlicher gezeigt haben
Brendan Metcalfe,
0

Hinweis: Der einfachste Unterschied zwischen sort () und sorted () besteht darin, dass sort () keinen Wert zurückgibt, während sorted () eine iterierbare Liste zurückgibt.

sort () gibt keinen Wert zurück.

Die sort () -Methode sortiert nur die Elemente einer bestimmten Liste in einer bestimmten Reihenfolge - Aufsteigend oder Absteigend, ohne einen Wert zurückzugeben.

Die Syntax der sort () -Methode lautet:

list.sort(key=..., reverse=...)

Alternativ können Sie für denselben Zweck auch die in Python integrierte Funktion sorted () verwenden. sortierte Funktion gibt sortierte Liste zurück

 list=sorted(list, key=..., reverse=...)
Projesh Bhoumik
quelle