li = [0, 1, 2, 3]
running = True
while running:
for elem in li:
thiselem = elem
nextelem = li[li.index(elem)+1]
Cuando esto llega al último elemento, un IndexError
se genera (como es el caso de cualquier lista, tupla, diccionario o cadena que se itera). En realidad quiero en ese punto para nextelem
A igual li[0]
. Mi solución bastante engorrosa para esto fue
while running:
for elem in li:
thiselem = elem
nextelem = li[li.index(elem)-len(li)+1] # negative index
¿Hay una mejor manera de hacer esto?
Después de pensarlo detenidamente, creo que esta es la mejor manera. Te permite bajarte en el medio fácilmente sin usar break
, que creo que es importante y requiere un cálculo mínimo, por lo que creo que es el más rápido. Tampoco requiere eso li
ser una lista o tupla. Podría ser cualquier iterador.
from itertools import cycle
li = [0, 1, 2, 3]
running = True
licycle = cycle(li)
# Prime the pump
nextelem = next(licycle)
while running:
thiselem, nextelem = nextelem, next(licycle)
Dejo las otras soluciones aquí para la posteridad.
Todo ese sofisticado iterador tiene su lugar, pero no aquí. Utilice el operador %.
li = [0, 1, 2, 3]
running = True
while running:
for idx, elem in enumerate(li):
thiselem = elem
nextelem = li[(idx + 1) % len(li)]
Ahora, si tiene la intención de recorrer infinitamente una lista, simplemente haga esto:
li = [0, 1, 2, 3]
running = True
idx = 0
while running:
thiselem = li[idx]
idx = (idx + 1) % len(li)
nextelem = li[idx]
Creo que es más fácil de entender que la otra solución que involucra tee
, y probablemente más rápido también. Si está seguro de que la lista no cambiará de tamaño, puede guardar una copia de len(li)
y usa eso.
Esto también le permite bajarse fácilmente de la rueda de la fortuna en el medio en lugar de tener que esperar a que el balde vuelva al fondo. Las otras soluciones (incluida la suya) requieren que compruebe running
en medio de la for
bucle y luego break
.
-
+1 Sí, esto también es simple y efectivo. No hay necesidad de estas soluciones funcionales innecesariamente complejas para problemas que tienen soluciones de procedimiento extremadamente simples. ¡Python no es un lenguaje funcional!
–Mark Byers
30 de enero de 2010 a las 13:37
-
@Mark Byers, ¡gracias! Creo que hay espacio para una solución bastante funcional si la lista es bastante pequeña, y la agregué. todo el rato con
running
no es funcional, y tratar de calzarlo en una solución funcional es feo.– Omnifaro
30 de enero de 2010 a las 13:53
-
@Mark Byers: Allí, la respuesta que creo que es mejor usa itertools, pero de una manera muy minimalista. Creo que es muy rápido y fácil de entender.
– Omnifaro
30 de enero de 2010 a las 14:13
-
Soy tan perfeccionista. Es irritante que después de 8 ediciones se convierta en una respuesta wiki de la comunidad. suspiro
– Omnifaro
30 de enero de 2010 a las 14:25
-
¡me encanta esto!
(idx + 1) % len(li)
– Jonathan
4 de febrero de 2018 a las 16:02
while running:
for elem,next_elem in zip(li, li[1:]+[li[0]]):
...
-
Este es mi segundo favorito, después del mío. 🙂 Simple es lo mejor, pero si la lista es bastante grande, esto crea dos copias de ella.
– Omnifaro
30 de enero de 2010 a las 13:34
-
Una de las cosas más pitónicas que he visto.
– Vicente Alex
18 mayo 2022 a las 21:22
Puede usar un iterador cíclico por pares:
from itertools import izip, cycle, tee
def pairwise(seq):
a, b = tee(seq)
next(b)
return izip(a, b)
for elem, next_elem in pairwise(cycle(li)):
...
-
Esto es bueno. Incorpora el ciclo while y el ciclo for en un ciclo conciso, que itera continuamente sobre los pares adyacentes en la lista y termina al final.
– Jason R. Coombs
30 de enero de 2010 a las 13:37
-
+1 por usar pairwise: una función de biblioteca no oficial que existe solo en la documentación de itertools. Entonces, aunque no puede importarlo, se sabe que funciona.
– Jason R. Coombs
30 de enero de 2010 a las 13:39
-
Creo que oscurece la prueba para ejecutarse dentro del ciclo for y requiere el uso de
break
no es tan buena idea.– Omnifaro
30 de enero de 2010 a las 13:45
while running:
lenli = len(li)
for i, elem in enumerate(li):
thiselem = elem
nextelem = li[(i+1)%lenli]
Una forma bastante diferente de resolver esto:
li = [0,1,2,3]
for i in range(len(li)):
if i < len(li)-1:
# until end is reached
print 'this', li[i]
print 'next', li[i+1]
else:
# end
print 'this', li[i]
Nirmal
Usa el método zip en Python. Esta función devuelve una lista de tuplas, donde la i-ésima tupla contiene el i-ésimo elemento de cada una de las secuencias de argumentos o iterables
while running:
for thiselem,nextelem in zip(li, li[1 : ] + li[ : 1]):
#Do whatever you want with thiselem and nextelem
Mehdi Jlifi
Tan simple como esto:
li = [0, 1, 2, 3]
while 1:
for i, item in enumerate(x):
k = i + 1 if i != len(x) - 1 else 0
print('Current index {} : {}'.format(i,li[k]))
Considere dejar de lado el ciclo while. Parece irrelevante para la pregunta. Si es relevante, considere explicar por qué.
– Jason R. Coombs
30 de enero de 2010 a las 13:36
Quiero recorrer una lista indefinidamente, de ahí la combinación de bucle while/for. Lo siento, no expliqué eso.
– ignorante
30 de enero de 2010 a las 13:50
Supongo que también, idealmente, le gustaría poder detenerse en la mitad del ciclo en lugar de solo al final.
– Omnifaro
30 de enero de 2010 a las 13:55
Sí. Estoy seguro de que podría usar
break
para eso.– ignorante
30 de enero de 2010 a las 14:45