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 itertools
mó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
chain
enlaza dos secuencias en una; se usa aquí para agregar una secuencia de un solo elemento [None]
aprevs
islice
se usa para hacer una secuencia de todos los elementos excepto el primero, luego chain
se usa para agregar un None
al final
- Ahora hay 3 secuencias independientes basadas en
some_iterable
ese aspecto:
prevs
: None, A, B, C, D, E
items
: A, B, C, D, E
nexts
: B, C, D, E, None
- finalmente
izip
se usa para cambiar 3 secuencias en una secuencia de tripletes.
Tenga en cuenta que se izip
detiene cuando se agota cualquier secuencia de entrada, por lo que el último elemento de prevs
se 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 prevs
pero izip
el comportamiento hace que eso sea redundante
También tenga en cuenta que tee
, izip
, islice
y chain
venir del itertools
mó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 zip
lugar de izip
. No hay necesidad de importación zip
, que está predefinido en python 3
- fuente