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
sorted
Sie 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 sorted
Kopierversion 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 sorted
Erstellen 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, sorted
wenn ich eine neue sortierte Liste der Daten benötige, und ich würde verwenden, list.sort
wenn ich eine Liste direkt sortieren muss, und dies meine Verwendung bestimmen lassen.
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"