Las soluciones hasta ahora solo se ocupan de las listas, y la mayoría están copiando la lista. En mi experiencia, muchas veces eso no es posible.
Además, no tienen en cuenta el hecho de que puede tener elementos repetidos en la lista.
El título de su pregunta dice "valores anterior y siguiente dentro de un bucle", pero si se ejecuta la mayoría de respuestas aquí dentro de un bucle, que va a terminar la iteración en la lista entera de nuevo en cada elemento para encontrarlo .
Así que acabo de crear una función que. usando el módulo itertools
, 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)
A continuación, utilizarlo en un bucle, y tendrás artículos anteriores y siguientes en él:
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
que va a trabajar con cualquier tamaño lista (porque no copia la lista), y con cualquier iterable (archivos, conjuntos, etc.). De esta forma, puede iterar sobre la secuencia y tener los elementos anteriores y siguientes 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 eficientemente 3 iteradores independientes más de la secuencia de entrada
chain
enlaces dos secuencias en uno; se utiliza aquí para añadir una secuencia de un solo elemento [None]
a prevs
islice
se utiliza para hacer una secuencia de todos los elementos excepto el primero, entonces chain
se utiliza para añadir una None
a su extremo
- Hay ahora 3 secuencias independientes basado en
some_iterable
que se parecen:
prevs
: None, A, B, C, D, E
items
: A, B, C, D, E
nexts
: B, C, D, E, None
- finalmente
izip
se utiliza para cambiar 3 secuencias en una secuencia de tripletes.
Tenga en cuenta que izip
se detiene cuando cualquier secuencia de entrada se agota, por lo que se tendrá en cuenta el último elemento de prevs
, lo que es correcto - no hay tal elemento que el último elemento sería su prev
. Podríamos tratar de quitarse los últimos elementos de prevs
pero el comportamiento izip
's que hace redundante
También tenga en cuenta que tee
, izip
, islice
y chain
provienen del módulo de itertools
; operan en sus secuencias de entrada sobre la marcha (perezosamente), lo que los hace eficientes y no introduce la necesidad de tener toda la secuencia en la memoria a la vez y en cualquier momento.
En python 3
, se mostrará un error al importar izip
, puede usar zip
en lugar de izip
. No hay necesidad de importar zip
, que está predefinido en python 3
-source
¿Qué debería pasar si foo está al principio o al final de la lista? Actualmente, esto saldrá de los límites de su matriz. – Brian
si necesita la primera aparición de "foo", luego haga "break" desde el bloque "for" cuando coincida. – van