webentwicklung-frage-antwort-db.com.de

Beste Weg, um eine "umgekehrte" Liste in Python zu erstellen?

Wie kann in Python am besten eine neue Liste erstellt werden, deren Elemente mit denen einer anderen Liste identisch sind, jedoch in umgekehrter Reihenfolge? (Ich möchte die vorhandene Liste nicht ändern.)

Hier ist eine Lösung, die mir eingefallen ist:

new_list = list(reversed(old_list))

Es ist auch möglich, old_list Zu duplizieren und das Duplikat dann umzukehren:

new_list = list(old_list) # or `new_list = old_list[:]`
new_list.reverse()

Gibt es eine bessere Option, die ich übersehen habe? Wenn nicht, gibt es einen zwingenden Grund (wie Effizienz), einen der oben genannten Ansätze gegenüber dem anderen zu verwenden?

83
davidchambers
newlist = oldlist[::-1]

Das [::-1] slicing (was meine Frau Anna gerne "Mars-Smiley" nennt ;-) bedeutet: Schneiden Sie die gesamte Sequenz mit einem Schritt von -1, d. h. in umgekehrter Reihenfolge. Es funktioniert für alle Sequenzen.

Beachten Sie, dass dieses (nd die von Ihnen erwähnten Alternativen) einer "flachen Kopie" entspricht, dh: Wenn die Elemente veränderlich sind und Sie Mutatoren auf ihnen nennen, die Mutationen in den Elementen, die in der ursprünglichen Liste enthalten sind sind auch in den Elementen in der umgekehrten Liste und umgekehrt. Wenn Sie das vermeiden müssen, wird ein copy.deepcopy (dabei handelt es sich immer um eine möglicherweise kostspielige Operation), gefolgt von einem .reverse, ist die einzig gute Option.

194
Alex Martelli

Nun lasst uns timeit . Hinweis: Alex's [::-1] ist am schnellsten :)

$ p -m timeit "ol = [1, 2, 3]; nl = list(reversed(ol))"
100000 loops, best of 3: 2.34 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = list(ol); nl.reverse();"
1000000 loops, best of 3: 0.686 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = ol[::-1];"
1000000 loops, best of 3: 0.569 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = [i for i in reversed(ol)];"
1000000 loops, best of 3: 1.48 usec per loop


$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 44.7 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(ol); nl.reverse();"
10000 loops, best of 3: 27.2 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = ol[::-1];"
10000 loops, best of 3: 24.3 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = [i for i in reversed(ol)];"
10000 loops, best of 3: 155 usec per loop

Update: Von inspectorG4dget vorgeschlagene Listenkompositionsmethode hinzugefügt. Ich lasse die Ergebnisse für sich sprechen.

53
Sam Dolan

Anpassungen

Es lohnt sich, einen Basisbenchmark/eine Anpassung für die Timeit-Berechnungen von sdolan bereitzustellen, die die Leistung von 'umgekehrt' ohne die oft unnötige list() -Umwandlung zeigen. Diese list() -Operation fügt der Laufzeit zusätzliche 26 usec hinzu und wird nur für den Fall benötigt, dass ein Iterator nicht akzeptabel ist.

Ergebnisse:

reversed(lst) -- 11.2 usecs

list(reversed(lst)) -- 37.1 usecs

lst[::-1] -- 23.6 usecs

Berechnungen:

# I ran this set of 100000 and came up with 11.2, twice:
python -m timeit "ol = [1, 2, 3]*1000; nl = reversed(ol)"
100000 loops, best of 3: 11.2 usec per loop

# This shows the overhead of list()
python -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 37.1 usec per loop

# This is the result for reverse via -1 step slices
python -m timeit "ol = [1, 2, 3]*1000;nl = ol[::-1]"
10000 loops, best of 3: 23.6 usec per loop

Schlussfolgerungen:

Die Schlussfolgerung dieser Tests ist, dass reversed() um 12,4 usec schneller ist als der Slice [::-1]

7
mekarpeles