Durchlaufen Sie eine Liste in Python in umgekehrter Reihenfolge


701

So kann ich beginnen len(collection)und enden in collection[0].

Ich möchte auch auf den Schleifenindex zugreifen können.

Antworten:


1181

Verwenden Sie die integrierte reversed()Funktion:

>>> a = ["foo", "bar", "baz"]
>>> for i in reversed(a):
...     print(i)
... 
baz
bar
foo

Um auch auf den ursprünglichen Index zuzugreifen, verwenden Sie ihn enumerate()in Ihrer Liste, bevor Sie ihn an reversed()folgende Adresse übergeben :

>>> for i, e in reversed(list(enumerate(a))):
...     print(i, e)
... 
2 baz
1 bar
0 foo

Da enumerate()ein Generator zurückgegeben wird und Generatoren nicht rückgängig gemacht werden können, müssen Sie ihn in einen listersten konvertieren .


130
Es wird keine Kopie erstellt, die Elemente werden beim Durchlaufen im Handumdrehen umgekehrt! Dies ist ein wichtiges Merkmal all dieser Iterationsfunktionen (die alle mit „ed“ enden).
Konrad Rudolph

9
@ Greg Hewgill Nein, es ist ein Iterator über dem Original, es wird keine Kopie erstellt!
André

92
Um die Verwirrung zu vermeiden: reversed()Ändert die Liste nicht. reversed()erstellt keine Kopie der Liste (andernfalls würde O (N) zusätzlichen Speicher benötigt). Wenn Sie die Liste ändern müssen, verwenden Sie alist.reverse(); Wenn Sie eine Kopie der Liste in umgekehrter Reihenfolge benötigen, verwenden Sie alist[::-1].
JFS

90
In dieser Antwort erstellt list (enumerate (a)) jedoch eine Kopie.
Triptychon

42
@ JF, reverse () erstellt keine Kopie, list (enumerate ()) erstellt jedoch eine Kopie.
Triptychon

172

Du kannst tun:

for item in my_list[::-1]:
    print item

(Oder was auch immer Sie in der for-Schleife tun möchten.)

Das [::-1]Slice kehrt die Liste in der for-Schleife um (ändert Ihre Liste jedoch nicht "dauerhaft").


24
[::-1]erstellt eine flache Kopie, daher ändert sich das Array weder "permanent" noch "temporär".
JFS

6
Dies ist etwas langsamer als die Verwendung von umgekehrt, zumindest unter Python 2.7 (getestet).
Kgriffs

14
So funktioniert diese Antwort : Es wird eine in Scheiben geschnittene Kopie der Liste mit den folgenden Parametern erstellt: Startpunkt : nicht angegeben (Länge der Liste beginnt am Ende), Endpunkt : nicht angegeben (wird zu einer anderen magischen Zahl als 0wahrscheinlich -1endet sie am Anfang) ) und Schritt : -1(iteriert rückwärts durch die Liste, jeweils ein 1Element).
Edward

1
Ich habe dies auch getestet (Python 2.7) und es war ~ 10% langsamer, [:: - 1] gegenreversed()
RustyShackleford zu verwenden.

67

Wenn Sie den Schleifenindex benötigen und nicht die gesamte Liste zweimal durchlaufen oder zusätzlichen Speicher verwenden möchten, würde ich einen Generator schreiben.

def reverse_enum(L):
   for index in reversed(xrange(len(L))):
      yield index, L[index]

L = ['foo', 'bar', 'bas']
for index, item in reverse_enum(L):
   print index, item

3
Ich würde die Funktion enumerate_reversed aufrufen, aber das könnte nur mein Geschmack sein. Ich glaube, Ihre Antwort ist die sauberste für die spezifische Frage.
Zot

1
reversed(xrange(len(L)))erzeugt die gleichen Indizes wie xrange(len(L)-1, -1, -1).
JFS

2
Ich bevorzuge weniger bewegliche Teile, um zu verstehen:for index, item in enumerate(reversed(L)): print len(L)-1-index, item
Don Kirkby

2
@Triptych Ich musste mich nur mit der Tatsache auseinandersetzen, dass die Aufzählung von reverse () keine umgekehrten Indizes liefert, und Ihr Code hat mir sehr geholfen. Diese Methode sollte sich in der Standardbibliothek befinden.
oski86

2
umgekehrt (xrange ()) funktioniert, weil ein xrange-Objekt die Methoden __reversed__ sowie die Methoden __len__ und __getitem__ hat und umgekehrt dies erkennen und verwenden kann. Ein Aufzählungsobjekt hat jedoch nicht __reversed__, __len__ oder __getitem__. Aber warum hat die Aufzählung sie nicht? Das weiß ich nicht.
FutureNerd

60

Es kann so gemacht werden:

für i im Bereich (len (Sammlung) -1, -1, -1):
    Drucksammlung [i]

    # print (Sammlung [i]) für Python 3. +

Ihre Vermutung war also ziemlich nah :) Ein wenig umständlich, aber es heißt im Grunde: Beginnen Sie mit 1 weniger als len(collection), fahren Sie fort, bis Sie kurz vor -1 in Schritten von -1 ankommen.

Zu Ihrer Information, die helpFunktion ist sehr nützlich, da Sie damit die Dokumente für etwas von der Python-Konsole aus anzeigen können, z.

help(range)


1
Für Versionen von Python vor 3.0 ist xrange meiner Meinung nach vorzuziehen, um große len (Sammlung) zu erreichen.
Brian M. Hunt

Ich glaube, Sie haben Recht :) iirc, range () generiert den gesamten Bereich als Array, aber xrange () gibt einen Iterator zurück, der nur die Werte generiert, die benötigt werden.
Alan Rowarth

11
Das sieht bei so vielen einfach zu komisch aus -1. Ich würde nur sagenreversed(xrange(len(collection)))
Musiphil

22

Die reversedeingebaute Funktion ist praktisch:

for item in reversed(sequence):

Die Dokumentation für umgekehrt erklärt die Einschränkungen.

Für die Fälle, in denen ich eine Sequenz zusammen mit dem Index in umgekehrter Reihenfolge durchlaufen muss (z. B. für direkte Änderungen, die die Sequenzlänge ändern), habe ich diese Funktion für mein Codeutil-Modul definiert:

import itertools
def reversed_enumerate(sequence):
    return itertools.izip(
        reversed(xrange(len(sequence))),
        reversed(sequence),
    )

Dieser vermeidet das Erstellen einer Kopie der Sequenz. Offensichtlich reversedgelten die Einschränkungen weiterhin.


9

Wie wäre es, wenn Sie keine neue Liste erstellen, indem Sie Folgendes indizieren:

>>> foo = ['1a','2b','3c','4d']
>>> for i in range(len(foo)):
...     print foo[-(i+1)]
...
4d
3c
2b
1a
>>>

ODER

>>> length = len(foo)
>>> for i in range(length):
...     print foo[length-i-1]
...
4d
3c
2b
1a
>>>

9
>>> l = ["a","b","c","d"]
>>> l.reverse()
>>> l
['d', 'c', 'b', 'a']

ODER

>>> print l[::-1]
['d', 'c', 'b', 'a']

7

Ich mag den Einzeiler-Generator-Ansatz:

((i, sequence[i]) for i in reversed(xrange(len(sequence))))

7

Sie können auch die Funktionen "Bereich" oder "Zählen" verwenden. Wie folgt:

a = ["foo", "bar", "baz"]
for i in range(len(a)-1, -1, -1):
    print(i, a[i])

3 baz
2 bar
1 foo

Sie können "count" auch aus itertools wie folgt verwenden:

a = ["foo", "bar", "baz"]
from itertools import count, takewhile

def larger_than_0(x):
    return x > 0

for x in takewhile(larger_than_0, count(3, -1)):
    print(x, a[x-1])

3 baz
2 bar
1 foo

Der Code in Ihrem ersten Block dort erzeugt nicht die richtige Ausgabe. die Ausgabe ist tatsächlich3 foo\n2 bar\n1 baz
amiller27

Verwenden Sie diesen Bereich "range (len (a) -1, -1, -1)", um die Verwendung von "a [i-1]" im ersten Beispiel zu vermeiden. Dies ist einfacher.
Francisc


4

Ein Ansatz ohne Importe:

for i in range(1,len(arr)+1):
    print(arr[-i])

oder

for i in arr[::-1]:
    print(i)

3
def reverse(spam):
    k = []
    for i in spam:
        k.insert(0,i)
    return "".join(k)

3

für was auch immer es wert ist, du kannst es auch so machen. sehr einfach.

a = [1, 2, 3, 4, 5, 6, 7]
for x in xrange(len(a)):
    x += 1
    print a[-x]

1
Sie können auch print a[-(x+1)]vermeiden, den Index im Hauptteil der Schleife neu zuzuweisen.
Malcolm

2

Ein ausdrucksstarker Weg, um reverse(enumerate(collection))in Python 3 zu erreichen :

zip(reversed(range(len(collection))), reversed(collection))

in Python 2:

izip(reversed(xrange(len(collection))), reversed(collection))

Ich bin mir nicht sicher, warum wir dafür keine Abkürzung haben, z.

def reversed_enumerate(collection):
    return zip(reversed(range(len(collection))), reversed(collection))

oder warum wir nicht haben reversed_range()


2

Wenn Sie den Index benötigen und Ihre Liste klein ist, ist es am besten zu lesen, reversed(list(enumerate(your_list)))wie in der akzeptierten Antwort angegeben. Aber dies erstellt eine Kopie der Liste, so dass , wenn Ihre Liste wird einen großen Teil Ihres Speichers Aufnahme finden Sie den Index zurück abziehen müssen enumerate(reversed())aus len()-1.

Wenn Sie es nur einmal tun müssen:

a = ['b', 'd', 'c', 'a']

for index, value in enumerate(reversed(a)):
    index = len(a)-1 - index

    do_something(index, value)

oder wenn Sie dies mehrmals tun müssen, sollten Sie einen Generator verwenden:

def enumerate_reversed(lyst):
    for index, value in enumerate(reversed(lyst)):
        index = len(lyst)-1 - index
        yield index, value

for index, value in enumerate_reversed(a):
    do_something(index, value)

1

Die Umkehrfunktion ist hier praktisch:

myArray = [1,2,3,4]
myArray.reverse()
for x in myArray:
    print x

list.reverse () hat keinen Rückgabewert
Georg Schölly

1

Sie können auch eine whileSchleife verwenden:

i = len(collection)-1
while i>=0:
    value = collection[i]
    index = i
    i-=1

1

Sie können einen negativen Index in einer normalen for-Schleife verwenden:

>>> collection = ["ham", "spam", "eggs", "baked beans"]
>>> for i in range(1, len(collection) + 1):
...     print(collection[-i])
... 
baked beans
eggs
spam
ham

Verwenden Sie Folgendes, um auf den Index zuzugreifen, als würden Sie eine umgekehrte Kopie der Sammlung vorwärts iterieren i - 1:

>>> for i in range(1, len(collection) + 1):
...     print(i-1, collection[-i])
... 
0 baked beans
1 eggs
2 spam
3 ham

Verwenden Sie Folgendes, um auf den ursprünglichen, nicht umgekehrten Index zuzugreifen len(collection) - i:

>>> for i in range(1, len(collection) + 1):
...     print(len(collection)-i, collection[-i])
... 
3 baked beans
2 eggs
1 spam
0 ham

1

Wenn es Ihnen nichts ausmacht, dass der Index negativ ist, können Sie Folgendes tun:

>>> a = ["foo", "bar", "baz"]
>>> for i in range(len(a)):
...     print(~i, a[~i]))
-1 baz
-2 bar
-3 foo

1

Ich denke, der eleganteste Weg ist, den folgenden Generator zu transformieren enumerateund zu reversedverwenden

(-(ri+1), val) for ri, val in enumerate(reversed(foo))

Dies erzeugt eine Umkehrung des enumerateIterators

Beispiel:

foo = [1,2,3]
bar = [3,6,9]
[
    bar[i] - val
    for i, val in ((-(ri+1), val) for ri, val in enumerate(reversed(foo)))
]

Ergebnis:

[6, 4, 2]

0

Die anderen Antworten sind gut, aber wenn Sie als Listenverständnisstil tun möchten

collection = ['a','b','c']
[item for item in reversed( collection ) ]

1
Ist das nicht dasselbe wie umgekehrt (Sammlung)? Das Hinzufügen des Listenverständnisses führt nur zu unnötigen Berechnungen. Es ist, als würde man a = [Element für Element in [1, 2, 3]] gegen a = [1, 2, 3] schreiben.
EpicDavi

0

So verwenden Sie negative Indizes: Beginnen Sie bei -1 und treten Sie bei jeder Iteration um -1 zurück.

>>> a = ["foo", "bar", "baz"]
>>> for i in range(-1, -1*(len(a)+1), -1):
...     print i, a[i]
... 
-1 baz
-2 bar
-3 foo

0

Ein einfacher Weg:

n = int(input())
arr = list(map(int, input().split()))

for i in reversed(range(0, n)):
    print("%d %d" %(i, arr[i]))

0
input_list = ['foo','bar','baz']
for i in range(-1,-len(input_list)-1,-1)
    print(input_list[i])

Ich denke, dies ist auch eine einfache Möglichkeit, dies zu tun ... vom Ende zu lesen und bis zur Länge der Liste weiter zu dekrementieren, da wir niemals den "End" -Index ausführen und daher auch -1 hinzufügen


0

Angenommen, die Aufgabe besteht darin, das letzte Element zu finden, das eine bestimmte Bedingung in einer Liste erfüllt (dh zuerst, wenn Sie rückwärts schauen), erhalte ich folgende Zahlen:

>>> min(timeit.repeat('for i in xrange(len(xs)-1,-1,-1):\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
4.6937971115112305
>>> min(timeit.repeat('for i in reversed(xrange(0, len(xs))):\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
4.809093952178955
>>> min(timeit.repeat('for i, x in enumerate(reversed(xs), 1):\n    if 128 == x: break', setup='xs, n = range(256), 0', repeat=8))
4.931743860244751
>>> min(timeit.repeat('for i, x in enumerate(xs[::-1]):\n    if 128 == x: break', setup='xs, n = range(256), 0', repeat=8))
5.548468112945557
>>> min(timeit.repeat('for i in xrange(len(xs), 0, -1):\n    if 128 == xs[i - 1]: break', setup='xs, n = range(256), 0', repeat=8))
6.286104917526245
>>> min(timeit.repeat('i = len(xs)\nwhile 0 < i:\n    i -= 1\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
8.384078979492188

Die hässlichste Option xrange(len(xs)-1,-1,-1)ist also die schnellste.


-1

Sie können einen Generator verwenden:

li = [1,2,3,4,5,6]
len_li = len(li)
gen = (len_li-1-i for i in range(len_li))

endlich:

for i in gen:
    print(li[i])

hoffe das hilft dir

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.