2

Suppose I have a list

xs = [0,1,2,3]
[some_function(current, next) for current, next in zip(xs, xs[1:])]

I want to iterate over pairs (current, next) of this list. To clarify zip creates list [(0,1), (1,2), (2,3)]

The problem is that if xs is a generator instead of list to achieve this with zip I would need to create a list from it and it is surely not the optimal solution.

user1685095
  • 5,438
  • 8
  • 45
  • 94
  • Despite the fact the proposed dupe says its input is a list, and this says the input *isn't* a list, the answer using `itertools.tee` is the same. – Steve Jessop Mar 11 '16 at 14:28

3 Answers3

7

You can use itertools.tee(iterable, n=2) which creates multiple independent iterators from one iterator.

my_iter, next_iter = tee(myiter)
next(nextiter)

[some_function(current, ne) for current, ne in zip(myiter, nextiter)]
maazza
  • 6,646
  • 15
  • 58
  • 94
Mazdak
  • 100,514
  • 17
  • 155
  • 179
1

This would work in case of infinite iterators etc.

def pairwise(iterator):
    """Iterate over pairs of an iterator."""
    last = next(iterator)
    while True:
        this = next(iterator)
        yield last, this
        last = this
L3viathan
  • 25,498
  • 2
  • 53
  • 71
  • I thought about that, but this will be slightly more complicated if you need itertate in triples, tuple of size n etc. – user1685095 Mar 11 '16 at 14:33
  • @user1685095 Then you could use a `deque` with `maxsize` set to n. But just use the other answer, I didn't know about `itertools.tee`. – L3viathan Mar 11 '16 at 14:36
-3

You can first transform the iterator into a list (if you are sure iterator can't be infinite):

xs = list(xs)
[some_function(current, next) for current, next in zip(xs, xs[1:])]
loutre
  • 854
  • 8
  • 15