Traverse una lista en orden inverso en Python
Pregunta
Para que pueda empezar desde len(collection)
y terminar en collection[0]
.
Edit: Lo siento, se me olvidó mencionar también quiero ser capaz de acceder al índice del bucle
.Solución
Utilice el built-in reversed()
función:
>>> a = ["foo", "bar", "baz"]
>>> for i in reversed(a):
... print(i)
...
baz
bar
foo
Para acceder también el índice original, utilice enumerate()
en su lista antes de pasar a reversed()
:
>>> for i, e in reversed(list(enumerate(a))):
... print(i, e)
...
2 baz
1 bar
0 foo
Desde enumerate()
devuelve un generador y generadores no se puede revertir, es necesario convertirlo en un list
primero.
Otros consejos
Puede hacer:
for item in my_list[::-1]:
print item
(o lo que usted quiere hacer en el bucle.)
La rebanada [::-1]
invierte la lista en el bucle for (pero en realidad no modificará su lista de "permanente").
Si se necesita el índice del bucle, y no quiere que atravesar toda la lista dos veces, o el uso de memoria adicional, me gustaría escribir un generador.
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
Se puede hacer así:
for i in range(len(collection)-1, -1, -1): print collection[i] # print(collection[i]) for python 3. +
Por lo que su suposición era bastante cerca :) Un poco incómodo pero es básicamente diciendo: empezar con menos de 1 len(collection)
, seguir adelante hasta llegar a justo antes de -1, en pasos de -1.
Para su información, la función help
es muy útil ya que le permite ver los documentos de algo de la consola de Python, por ejemplo:
help(range)
La función incorporada reversed
es práctico:
for item in reversed(sequence):
El documentación para invertido explica sus limitaciones.
En los casos en los que tienen que caminar una secuencia a la inversa junto con el índice (por ejemplo, para modificaciones en lugar cambiando la longitud de la secuencia), tengo esta función se define un módulo de mi codeutil:
import itertools
def reversed_enumerate(sequence):
return itertools.izip(
reversed(xrange(len(sequence))),
reversed(sequence),
)
Éste evita la creación de una copia de la secuencia. Obviamente, todavía se aplican las limitaciones reversed
.
>>> l = ["a","b","c","d"]
>>> l.reverse()
>>> l
['d', 'c', 'b', 'a']
o
>>> print l[::-1]
['d', 'c', 'b', 'a']
¿Qué tal sin volver a crear una nueva lista, puede hacerlo mediante la indexación:
>>> foo = ['1a','2b','3c','4d']
>>> for i in range(len(foo)):
... print foo[-(i+1)]
...
4d
3c
2b
1a
>>>
o
>>> length = len(foo)
>>> for i in range(length):
... print foo[length-i-1]
...
4d
3c
2b
1a
>>>
Me gusta el enfoque generador de una sola línea:
((i, sequence[i]) for i in reversed(xrange(len(sequence))))
Además, se puede usar cualquiera de las funciones "Count" "rango" o. Como sigue:
a = ["foo", "bar", "baz"]
for i in range(len(a)-1, -1, -1):
print(i, a[i])
3 baz
2 bar
1 foo
También es posible usar "recuento" de itertools de la siguiente manera:
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
Uso list.reverse()
y luego repetir como lo haría normalmente.
def reverse(spam):
k = []
for i in spam:
k.insert(0,i)
return "".join(k)
para lo que cada vez que vale la pena que puede hacerlo de esta manera también. muy simple.
a = [1, 2, 3, 4, 5, 6, 7]
for x in xrange(len(a)):
x += 1
print a[-x]
Si necesita el índice y su lista es pequeña, la forma más legible es hacer reversed(list(enumerate(your_list)))
como la respuesta aceptada dice. Pero esto crea una copia de su lista, por lo que si su lista está ocupando una gran parte de la memoria que tendrá que restar el índice devuelto por enumerate(reversed())
de len()-1
.
Si sólo tiene que hacerlo una vez:
a = ['b', 'd', 'c', 'a']
for index, value in enumerate(reversed(a)):
index = len(a)-1 - index
do_something(index, value)
o si usted tiene que hacer esto varias veces se debe utilizar un generador:
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)
la función inversa es muy útil aquí:
myArray = [1,2,3,4]
myArray.reverse()
for x in myArray:
print x
Las otras respuestas son buenas, pero si quieren hacer tan Lista estilo comprensión
collection = ['a','b','c']
[item for item in reversed( collection ) ]
uso reversed()
función incorporada para objeto de secuencia, este método tiene el efecto de todas las secuencias
También puede utilizar un bucle while
:
i = len(collection)-1
while i>=0:
value = collection[i]
index = i
i-=1
Puede utilizar un índice negativo en un ordinario para el bucle:
>>> collection = ["ham", "spam", "eggs", "baked beans"]
>>> for i in range(1, len(collection) + 1):
... print(collection[-i])
...
baked beans
eggs
spam
ham
Para acceder al índice como si estuviera iterando hacia adelante sobre una copia invertida de la colección, utilice i - 1
:
>>> for i in range(1, len(collection) + 1):
... print(i-1, collection[-i])
...
0 baked beans
1 eggs
2 spam
3 ham
Para acceder al índice original, no invertida, utilice 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
Una manera expresiva para lograr reverse(enumerate(collection))
en Python 3:
zip(reversed(range(len(collection))), reversed(collection))
en Python 2:
izip(reversed(xrange(len(collection))), reversed(collection))
No estoy seguro de por qué no tenemos una taquigrafía para esto, por ejemplo:.
def reversed_enumerate(collection):
return zip(reversed(range(len(collection))), reversed(collection))
o por qué no tenemos reversed_range()
Un enfoque sin importaciones:
for i in range(1,len(arr)+1):
print(arr[-i])
o
for i in arr[::-1]:
print(i)
Para utilizar índices negativos:. Comenzará a -1 y paso atrás por -1 en cada iteración
>>> a = ["foo", "bar", "baz"]
>>> for i in range(-1, -1*(len(a)+1), -1):
... print i, a[i]
...
-1 baz
-2 bar
-3 foo
Una manera simple:
n = int(input())
arr = list(map(int, input().split()))
for i in reversed(range(0, n)):
print("%d %d" %(i, arr[i]))
input_list = ['foo','bar','baz']
for i in range(-1,-len(input_list)-1,-1)
print(input_list[i])
Creo que éste es también forma sencilla de hacerlo ... leer desde el final y seguir disminuyendo hasta que la longitud de la lista, ya que nunca ejecutamos el índice "final" por lo tanto, también añadió -1
Suponiendo es encontrar último elemento que satisface alguna condición en una lista (es decir, en primer lugar cuando se mira hacia atrás), estoy consiguiendo los siguientes números:
>>> 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
Por lo tanto, la opción xrange(len(xs)-1,-1,-1)
más feo es el más rápido.
Si no te importa el índice es negativo, que puede hacer:
>>> a = ["foo", "bar", "baz"]
>>> for i in range(len(a)):
... print(~i, a[~i]))
-1 baz
-2 bar
-3 foo
Creo que la forma más elegante es transformar enumerate
y reversed
utilizando el siguiente generador
(-(ri+1), val) for ri, val in enumerate(reversed(foo))
que genera una el reverso del iterador enumerate
Ejemplo:
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)))
]
Resultados:
[6, 4, 2]