Iterador de filtragem eficiente para Python

Você já quis filtrar um iterador em dois “sub” iteradores? Agora você pode:

>>> even, odd = sift(xrange(10), lambda x: x % 2 == 0)
>>> list(even)
[0, 2, 4, 6, 8]
>>> list(odd)
[1, 3, 5, 7, 9]

Observe que o iterável de entrada é consumido apenas lentamente:

>>> X = iter(xrange(10))
>>> even, odd = sift(X, lambda x: x % 2 == 0)
>>> X.next()
0
>>> X.next()
1
>>> X.next()
2
>>> list(even)
[4, 6, 8]
>>> list(odd)
[3, 5, 7, 9]

Um pequeno aviso

Esteja ciente de que, para consumir totalmente um dos iteradores retornados, você pode estar consumindo uma grande parte da iteração de entrada e mantendo seus valores em buffer na memória. É melhor consumir o maior iterável primeiro, sempre que possível:

>>> small_ones, large_ones = sift(xrange(10000), lambda x: x < 9000)

# low memory peak (no buffering needed)
>>> list(small_ones)
[0, ..., 8999]
>>> list(large_ones)
[9000, ..., 9999]

# at its peak, 9000 items are buffered in memory
>>> list(large_ones)
[9000, ..., 9999]
>>> list(small_ones)
[0, ..., 8999]

A implementação: https://gist.github.com/nvie/5804375