Aqui está um exemplo relevante dos documentos do módulo itertools :
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
Para Python 2, você precisa, em itertools.izip
vez de zip
:
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return itertools.izip(a, b)
Como isso funciona:
Primeiro, dois iteradores paralelos a
e b
são criados (a tee()
chamada), ambos apontando para o primeiro elemento do iterável original. O segundo iterador b
é movido 1 passo à frente (a next(b, None)
) chamada. Nesse ponto, a
aponte para s0 e b
aponte para s1. Ambos a
e b
podem atravessar o iterador original independentemente - a função izip pega os dois iteradores e faz pares dos elementos retornados, avançando os dois iteradores no mesmo ritmo.
Uma ressalva: a tee()
função produz dois iteradores que podem avançar independentemente um do outro, mas tem um custo. Se um dos iteradores avançar mais que o outro, será tee()
necessário manter os elementos consumidos na memória até o segundo iterador consumi-los também (ele não pode 'rebobinar' o iterador original). Aqui não importa, porque um iterador está apenas um passo à frente do outro, mas, em geral, é fácil usar muita memória dessa maneira.
E como tee()
pode assumir um n
parâmetro, isso também pode ser usado para mais de dois iteradores paralelos:
def threes(iterator):
"s -> (s0,s1,s2), (s1,s2,s3), (s2, s3,4), ..."
a, b, c = itertools.tee(iterator, 3)
next(b, None)
next(c, None)
next(c, None)
return zip(a, b, c)