As soluções até agora lidam apenas com listas, e a maioria está copiando a lista. Na minha experiência, muitas vezes isso não é possível.
Além disso, eles não lidam com o fato de que você pode ter elementos repetidos na lista.
O título da sua pergunta diz " Valores anteriores e próximos dentro de um loop ", mas se você executar a maioria das respostas aqui dentro de um loop, acabará iterando a lista inteira novamente em cada elemento para encontrá-lo.
Acabei de criar uma função que. usando o itertoolsmódulo, divide e divide o iterável e gera tuplas com os elementos anteriores e seguintes juntos. Não é exatamente o que seu código faz, mas vale a pena dar uma olhada, porque provavelmente pode resolver seu 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)
Em seguida, use-o em um loop e você terá os itens anteriores e os próximos nele:
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
Os 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á com qualquer lista de tamanho (porque não copia a lista), e com qualquer iterável (arquivos, conjuntos, etc). Dessa forma, você pode apenas iterar sobre a sequência e ter os itens anteriores e posteriores disponíveis dentro do loop. Não há necessidade de pesquisar novamente o item na sequência.
Uma breve explicação do código:
tee é usado para criar com eficiência 3 iteradores independentes sobre a sequência de entrada
chainliga duas sequências em uma; é usado aqui para anexar uma sequência de elemento único [None]aprevs
isliceé usado para fazer uma sequência de todos os elementos exceto o primeiro, então chainé usado para adicionar a Noneao seu final
- Existem agora 3 sequências independentes baseadas em
some_iterableque se parecem com:
prevs: None, A, B, C, D, E
items: A, B, C, D, E
nexts: B, C, D, E, None
- finalmente
izipé usado para alterar 3 sequências em uma sequência de tripletos.
Observe que izippara quando qualquer sequência de entrada se esgota, então o último elemento de prevsserá ignorado, o que é correto - não existe tal elemento que o último elemento seria seu prev. Poderíamos tentar remover os últimos elementos, prevsmas izipo comportamento torna isso redundante
Observe também que tee, izip, islicee chainvêm do itertoolsmódulo; eles operam em suas sequências de entrada em tempo real (preguiçosamente), o que os torna eficientes e não introduz a necessidade de ter toda a sequência na memória de uma vez a qualquer momento.
Em python 3, ele mostrará um erro durante a importação izip, você pode usar em zipvez de izip. Não há necessidade de importação zip, que é pré-definido na python 3- fonte