1351 Stimmen

Wie kann man eine Liste umkehren?

Wie kann ich in Python rückwärts über eine Liste iterieren?

array = [0, 10, 20, 40]
for (i = array.length() - 1; i >= 0; i--)

1664voto

codaddict Punkte 426877

Verwenden Sie die reversed Funktion:

>>> xs = [0, 10, 20, 40]
>>> for i in reversed(xs):
...     print(i)

Um eine umgekehrte Liste zu erhalten:

>>> list(reversed(xs))
[40, 20, 10, 0]

1518voto

mechanical_meat Punkte 154171
>>> xs = [0, 10, 20, 40]
>>> xs[::-1]
[40, 20, 10, 0]

Erweiterte Slice-Syntax wird erklärt aquí . Siehe auch, Dokumentation .

460voto

ghostdog74 Punkte 305138
>>> L = [0,10,20,40]
>>> L.reverse()
>>> L
[40, 20, 10, 0]

Oder

>>> L[::-1]
[40, 20, 10, 0]

59voto

LightCC Punkte 7512

Zusammenfassung der Methoden mit Erläuterung und zeitlichen Ergebnissen

Es gibt drei verschiedene eingebaute Möglichkeiten, eine Liste umzukehren. Welche Methode die beste ist, hängt davon ab, ob Sie es brauchen:

  1. Eine bestehende Liste an Ort und Stelle umkehren (Änderung der ursprünglichen Listenvariablen)
    • Die beste Lösung ist object.reverse() Methode
  2. Erstellen Sie einen Iterator der umgekehrten Liste (da Sie diese in eine for-Schleife, einen Generator usw. einspeisen werden).
    • Die beste Lösung ist reversed(object) der den Iterator erzeugt
  3. Erstellen Sie eine Kopie der Liste, nur in umgekehrter Reihenfolge (um die ursprüngliche Liste zu erhalten)
    • Die beste Lösung ist die Verwendung von Slices mit einer Schrittweite von -1: object[::-1]

Aus Sicht der Geschwindigkeit ist es am besten, die oben genannten eingebauten Funktionen zu verwenden, um eine Liste umzukehren. Sie sind bei kurzen Listen (10 Elemente) 2 bis 8 Mal schneller und bei langen Listen bis zu 300 Mal schneller als eine manuell erstellte Schleife oder ein Generator. Das macht Sinn - sie sind in einer Muttersprache (z. B. C) geschrieben, werden von Experten erstellt, geprüft und optimiert. Sie sind auch weniger fehleranfällig und können eher mit Rand- und Eckfällen umgehen.

Test-Skript

Fügen Sie alle Codeschnipsel in dieser Antwort zusammen, um ein Skript zu erstellen, das die verschiedenen Möglichkeiten der Umkehrung einer Liste, die unten beschrieben werden, ausführt. Es wird jede Methode 100.000 Mal ausführen und dabei die Zeit messen. Die Ergebnisse sind im letzten Abschnitt für Listen der Länge 2, 10 und 1000 Elemente dargestellt.

from timeit import timeit
from copy import copy

def time_str_ms(t):
    return '{0:8.2f} ms'.format(t * 1000)

Methode 1: Umkehrung an Ort und Stelle mit obj.reverse()

Wenn das Ziel nur darin besteht, die Reihenfolge der Elemente in einer vorhandenen Liste umzukehren, ohne sie in einer Schleife zu bearbeiten oder eine Kopie zu erhalten, verwenden Sie die <list>.reverse() Funktion. Wenn Sie diese Funktion direkt auf ein Listenobjekt anwenden, wird die Reihenfolge aller Elemente umgekehrt:

Beachten Sie, dass die folgende Funktion die angegebene Originalvariable umkehrt, obwohl sie auch die umgekehrte Liste zurückgibt, d. h. Sie können mit dieser Funktionsausgabe eine Kopie erstellen. Normalerweise würde man dafür keine Funktion erstellen, aber das Timing-Skript erfordert dies.

Wir testen die Leistung dieses Verfahrens auf zwei Arten - zunächst wird eine Liste einfach an Ort und Stelle umgekehrt (die ursprüngliche Liste wird geändert), und dann wird die Liste kopiert und anschließend umgekehrt, um festzustellen, ob dies im Vergleich zu den anderen Verfahren der schnellste Weg zur Erstellung einer umgekehrten Kopie ist.

def rev_in_place(mylist):
    mylist.reverse()
    return mylist

def rev_copy_reverse(mylist):
    a = copy(mylist)
    a.reverse()
    return a

Methode 2: Umkehrung einer Liste mithilfe von Slices obj[::-1]

Die eingebaute Index-Slicing-Methode ermöglicht es Ihnen, eine Kopie eines Teils eines beliebigen indizierten Objekts zu erstellen.

  • Sie hat keine Auswirkungen auf das ursprüngliche Objekt
  • Es wird eine vollständige Liste erstellt, kein Iterator

Die generische Syntax lautet: <object>[first_index:last_index:step] . Verwenden Sie die Slicing-Funktion, um eine einfache umgekehrte Liste zu erstellen: <list>[::-1] . Wenn eine Option leer gelassen wird, werden sie auf die Standardwerte des ersten und letzten Elements des Objekts gesetzt (umgekehrt, wenn die Schrittweite negativ ist).

Die Indizierung ermöglicht die Verwendung negativer Zahlen, die vom Ende des Objektindex rückwärts zählen (d. h. -2 ist das vorletzte Element). Wenn die Schrittweite negativ ist, wird mit dem letzten Element begonnen und um diesen Betrag rückwärts indiziert.

def rev_slice(mylist):
    a = mylist[::-1]
    return a

Methode 3: Umkehrung einer Liste mit der reversed(obj) Iteratorfunktion

Es gibt eine reversed(indexed_object) Funktion:

  • Dies erzeugt einen umgekehrten Index-Iterator, keine Liste. Ideal, wenn Sie ihn in eine Schleife einfügen, um die Leistung bei großen Listen zu verbessern
  • Dadurch wird eine Kopie erstellt, die das Originalobjekt nicht beeinflusst.

Testen Sie sowohl mit einem rohen Iterator als auch mit der Erstellung einer Liste aus dem Iterator.

def reversed_iterator(mylist):
    a = reversed(mylist)
    return a

def reversed_with_list(mylist):
    a = list(reversed(mylist))
    return a

Methode 4: Umgekehrte Liste mit benutzerdefinierter/manueller Indizierung

Wie das Timing zeigt, ist es keine gute Idee, eigene Indizierungsmethoden zu entwickeln. Verwenden Sie die eingebauten Methoden, es sei denn, Sie müssen wirklich etwas Eigenes machen. Das bedeutet einfach, dass Sie die eingebauten Methoden lernen müssen.

Bei kleineren Listen ist der Nachteil nicht so groß, aber wenn man die Liste vergrößert, wird der Nachteil gewaltig. Der nachstehende Code könnte sicher optimiert werden, aber er kann niemals mit den eingebauten Methoden mithalten, da diese direkt in einer Muttersprache implementiert sind.

def rev_manual_pos_gen(mylist):
    max_index = len(mylist) - 1
    return [ mylist[max_index - index] for index in range(len(mylist)) ]

def rev_manual_neg_gen(mylist):
    ## index is 0 to 9, but we need -1 to -10
    return [ mylist[-index-1] for index in range(len(mylist)) ]

def rev_manual_index_loop(mylist):
    a = []
    reverse_index = len(mylist) - 1
    for index in range(len(mylist)):
        a.append(mylist[reverse_index - index])
    return a

def rev_manual_loop(mylist):
    a = []
    reverse_index = len(mylist)
    for index, _ in enumerate(mylist):
        reverse_index -= 1
        a.append(mylist[reverse_index])
    return a

Zeitplan für jede Methode

Nachfolgend finden Sie den Rest des Skripts, um die Zeit für jede Methode der Umkehrung. Es zeigt die Umkehrung an Ort und Stelle mit obj.reverse() und die Erstellung der reversed(obj) Iterator sind immer am schnellsten, während die Verwendung von Slices der schnellste Weg ist, eine Kopie zu erstellen.

Es beweist auch, dass man nicht versuchen sollte, einen eigenen Weg zu finden, wenn man nicht muss!

loops_to_test = 100000
number_of_items = 10
list_to_reverse = list(range(number_of_items))
if number_of_items < 15:
    print("a: {}".format(list_to_reverse))
print('Loops: {:,}'.format(loops_to_test))
# List of the functions we want to test with the timer, in print order
fcns = [rev_in_place, reversed_iterator, rev_slice, rev_copy_reverse,
        reversed_with_list, rev_manual_pos_gen, rev_manual_neg_gen,
        rev_manual_index_loop, rev_manual_loop]
max_name_string = max([ len(fcn.__name__) for fcn in fcns ])
for fcn in fcns:
    a = copy(list_to_reverse) # copy to start fresh each loop
    out_str = ' | out = {}'.format(fcn(a)) if number_of_items < 15 else ''
    # Time in ms for the given # of loops on this fcn
    time_str = time_str_ms(timeit(lambda: fcn(a), number=loops_to_test))
    # Get the output string for this function
    fcn_str = '{}(a):'.format(fcn.__name__)
    # Add the correct string length to accommodate the maximum fcn name
    format_str = '{{fx:{}s}} {{time}}{{rev}}'.format(max_name_string + 4)
    print(format_str.format(fx=fcn_str, time=time_str, rev=out_str))

Timing-Ergebnisse

Die Ergebnisse zeigen, dass die Skalierung am besten mit den eingebauten Methoden funktioniert, die für eine bestimmte Art der Umkehrung am besten geeignet sind. Mit anderen Worten, wenn die Anzahl der Objektelemente zunimmt, sind die eingebauten Methoden den anderen Methoden sogar überlegen.

Die eingebaute Methode, die direkt das erreicht, was Sie brauchen, ist besser als die Aneinanderreihung von Dingen. D.h. Slicing ist am besten, wenn Sie eine Kopie der umgekehrten Liste benötigen - es ist schneller als die Erstellung einer doppelten Liste aus list(reversed(obj)) Funktion und schneller als eine Kopie der Liste zu erstellen und dann eine In-Place obj.reverse() aber nie um mehr als die doppelte Geschwindigkeit. Inzwischen können benutzerdefinierte Methoden bei großen Listen um Größenordnungen länger dauern.

Für die Skalierung bei einer Liste mit 1000 Einträgen wird die reversed(<list>) Funktionsaufruf braucht ~30 ms, um den Iterator einzurichten, die Umkehrung an Ort und Stelle braucht nur ~55 ms, die Verwendung der Slice-Methode braucht ~210 ms, um eine Kopie der vollständigen umgekehrten Liste zu erstellen, aber die schnellste manuelle Methode, die ich gemacht habe, brauchte ~8400 ms .

Mit 2 Einträgen in der Liste:

a: [0, 1]
Loops: 100,000
rev_in_place(a):             24.70 ms | out = [1, 0]
reversed_iterator(a):        30.48 ms | out = <list_reverseiterator object at 0x0000020242580408>
rev_slice(a):                31.65 ms | out = [1, 0]
rev_copy_reverse(a):         63.42 ms | out = [1, 0]
reversed_with_list(a):       48.65 ms | out = [1, 0]
rev_manual_pos_gen(a):       98.94 ms | out = [1, 0]
rev_manual_neg_gen(a):       88.11 ms | out = [1, 0]
rev_manual_index_loop(a):    87.23 ms | out = [1, 0]
rev_manual_loop(a):          79.24 ms | out = [1, 0]

Die Liste enthält 10 Einträge:

rev_in_place(a):             23.39 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
reversed_iterator(a):        30.23 ms | out = <list_reverseiterator object at 0x00000290A3CB0388>
rev_slice(a):                36.01 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_copy_reverse(a):         64.67 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
reversed_with_list(a):       50.77 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_pos_gen(a):      162.83 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_neg_gen(a):      167.43 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_index_loop(a):   152.04 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_loop(a):         183.01 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Und mit 1000 Einträgen auf der Liste:

rev_in_place(a):             56.37 ms
reversed_iterator(a):        30.47 ms
rev_slice(a):               211.42 ms
rev_copy_reverse(a):        295.74 ms
reversed_with_list(a):      418.45 ms
rev_manual_pos_gen(a):     8410.01 ms
rev_manual_neg_gen(a):    11054.84 ms
rev_manual_index_loop(a): 10543.11 ms
rev_manual_loop(a):       15472.66 ms

32voto

Pawan Kumar Punkte 1894

Für die Umkehrung der gleichen Liste verwenden Sie:

array.reverse()

Um eine umgekehrte Liste einer anderen Liste zuzuordnen, verwenden Sie:

newArray = array[::-1]

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X