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,787
  • 9
  • 51
  • 100
  • 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
  • 7,016
  • 15
  • 63
  • 96
Mazdak
  • 105,000
  • 18
  • 159
  • 188
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
  • 26,748
  • 2
  • 58
  • 81
  • 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
  • 874
  • 8
  • 16