Solutions so far only deal with lists, and most copies the list. In my experience, many times this was not possible.
Also, they are not related to the fact that you can have duplicate items in a list.
The title of your question reads “Previous and next values inside the loop,” but if you follow most of the answers here inside the loop, you end up iterating the whole list again for each element to find it.
So I just created a function that. using the itertools module, itertools and splits the iterable and generates tuples with the previous and next elements together. Not exactly what your code does, but worth a look, because it can probably solve your problem.
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)
Then use it in a loop and you will have the previous and next elements:
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
Results, achievements:
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
It will work with any list of sizes (because it does not copy the list) and with any repeatable ones (files, sets, etc.). Thus, you can simply iterate over the sequence and have the previous and next elements in the loop. No need to search for an element in a sequence again
A brief explanation of the code:
tee used to efficiently create 3 independent iterators over the input sequencechain connects two sequences into one; here it is used to add a singleton sequence [None] to prevsislice used to create a sequence of all elements except the first, then chain used to add None to the end- Now there are 3 independent sequences based on
some_iterable that look like this:prevs : None, A, B, C, D, Eitems : A, B, C, D, Enexts : B, C, D, E, None
- finally,
izip used to change 3 sequences into one triplet sequence.
Please note that izip stops when any input sequence is exhausted, so the last prevs element will be ignored, and rightly so - there is no such element that its last element would be prev . We could try to remove the last elements from prevs but the izip behavior makes this redundant
Also note that tee , izip , islice and chain come from the itertools module; they work on their input sequences “on the fly” (lazily), which makes them efficient and does not create the need to have the entire sequence immediately in memory at any time.
In python 3 , an izip will appear when importing izip , you can use zip instead of izip . No need to import zip , this is predefined in python 3 - source code