Las soluciones hasta ahora solo tratan con listas, y la mayoría está copiando la lista. En mi experiencia, muchas veces eso no es posible.
Además, no abordan el hecho de que puede tener elementos repetidos en la lista.
El título de su pregunta dice " Valores anteriores y siguientes dentro de un ciclo ", pero si ejecuta la mayoría de las respuestas aquí dentro de un ciclo, terminará iterando sobre la lista completa nuevamente en cada elemento para encontrarlo.
Así que acabo de crear una función que. usando el itertoolsmódulo, divide y corta el iterable, y genera tuplas con los elementos anterior y siguiente juntos. No es exactamente lo que hace su código, pero vale la pena echarle un vistazo, porque probablemente pueda resolver su problema.
from itertools import tee, islice, chain, izip
def previous_and_next(some_iterable):
prevs, items, nexts = tee(some_iterable, 3)
prevs = chain([None], prevs)
nexts = chain(islice(nexts, 1, None), [None])
return izip(prevs, items, nexts)
Luego utilícelo en un bucle, y tendrá elementos anteriores y siguientes:
mylist = ['banana', 'orange', 'apple', 'kiwi', 'tomato']
for previous, item, nxt in previous_and_next(mylist):
print "Item is now", item, "next is", nxt, "previous is", previous
Los resultados:
Item is now banana next is orange previous is None
Item is now orange next is apple previous is banana
Item is now apple next is kiwi previous is orange
Item is now kiwi next is tomato previous is apple
Item is now tomato next is None previous is kiwi
Funcionará con listas de cualquier tamaño (porque no copia la lista) y con cualquier iterable (archivos, conjuntos, etc.). De esta manera, puede iterar sobre la secuencia y tener los elementos anterior y siguiente disponibles dentro del ciclo. No es necesario volver a buscar el elemento en la secuencia.
Una breve explicación del código:
tee se utiliza para crear de manera eficiente 3 iteradores independientes sobre la secuencia de entrada
chainenlaza dos secuencias en una; se usa aquí para agregar una secuencia de un solo elemento [None]aprevs
islicese usa para hacer una secuencia de todos los elementos excepto el primero, luego chainse usa para agregar un Noneal final
- Ahora hay 3 secuencias independientes basadas en
some_iterableese aspecto:
prevs: None, A, B, C, D, E
items: A, B, C, D, E
nexts: B, C, D, E, None
- finalmente
izipse usa para cambiar 3 secuencias en una secuencia de tripletes.
Tenga en cuenta que se izipdetiene cuando se agota cualquier secuencia de entrada, por lo que el último elemento de prevsse ignorará, lo cual es correcto: no existe tal elemento que el último elemento sería suyo prev. Podríamos intentar quitar los últimos elementos de prevspero izipel comportamiento hace que eso sea redundante
También tenga en cuenta que tee, izip, islicey chainvenir del itertoolsmódulo; operan en sus secuencias de entrada sobre la marcha (perezosamente), lo que las hace eficientes y no introduce la necesidad de tener la secuencia completa en la memoria de una vez en ningún momento.
En python 3, mostrará un error al importar izip, puede usar en ziplugar de izip. No hay necesidad de importación zip, que está predefinido en python 3- fuente