Sometimes it's useful to iterate through a series of items, looking at an item and the next one.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | def two_finger(iterable):
"""
>>> sequence = [1, 3, 9, 5, 22, 11]
>>> for item, next in two_finger(sequence):
... print item, next
...
1 3
3 9
9 5
5 22
22 11
"""
iterator = iter(iterable)
item = iterator.next()
while True:
try:
next = iterator.next()
yield item, next
item = next
except StopIteration:
return
|
What about:
Don't use my way if iterating has side effects however
For longer seq i'd rather do that: (in Python 2.x)
But we still iterate over it twice.
So (in case of long seqences) the recipe by Karl is better.
You can also express the same idea in such a way:
I like Jan's final suggestion. I've modified my own copy to:
The other problem with the code in comment #1 is that it really only works for lists. You can't use it with, say, xrange. Jan's first alternative works for sequences, but not for generators. If you use generators, you have to use islice(seq, 0, None)--but then it won't work with indexable sequences.
Neither
islice(seq, 1, None)
norislice(seq, 0, None)
do the task correctly using generators (and generally iterators). Of course, not because of using islice (it works with generators very well), but because the same iterator object is used twice by izip.To have a universal solution this way, we'd use itertools.tee to split iterator into two, e.g.:
Though I'd preffer the solution with one iterator and
item = next_item
.From the documentation of itertools ("Recipes" section, which is a very fine read):
Leave it to the people who wrote the language to come up with the best version. :)