Есть ли в Python встроенная функция для чередования генераторов / последовательностей? - PullRequest
13 голосов
/ 07 января 2012

Я заметил, что itertools не имеет (как мне кажется) функции, способной чередовать элементы из нескольких других итерируемых объектов (в отличие от архивирования их):

def leaf(*args): return (it.next() for it in cycle(imap(chain,args)))
tuple(leaf(['Johann', 'Sebastian', 'Bach'], repeat(' '))) => ('Johann', ' ', 'Sebastian', ' ', 'Bach', ' ')

(Правка) Причина, по которой я спрашиваю, заключается в том, что я хочу избежать ненужных вхождений zip / flatten.

Очевидно, определение leaf достаточно просто, но если есть предопределенная функция, которая делает то же самое, я бы предпочел использовать это, или очень четкое выражение генератора. Есть ли такая встроенная функция, в itertools или в какой-либо другой известной библиотеке, или подходящее идиоматическое выражение?

Редактировать 2: возможно даже более краткое определение (с использованием пакета functional):

from itertools import *
from functional import *

compose_mult = partial(reduce, compose)
leaf = compose_mult((partial(imap, next), cycle, partial(imap, chain), lambda *args: args))

Ответы [ 2 ]

10 голосов
/ 07 января 2012

Вы ищете встроенные zip и itertools.chain.from_iterable, чтобы сгладить результат:

>>> import itertools
>>> list(zip(['Johann', 'Sebastian', 'Bach'], itertools.repeat(' ')))
[('Johann', ' '), ('Sebastian', ' '), ('Bach', ' ')]
>>> list(itertools.chain.from_iterable(_))
['Johann', ' ', 'Sebastian', ' ', 'Bach', ' ']

Обратите внимание, что я использовал list просто чтобы получить хороший вывод.Используя стандартные itertools, альтернативные реализации для leaf будут:

leaf = lambda *a: itertools.chain.from_iterable(itertools.izip(*a)) # Python 2.x
leaf = lambda *a: itertools.chain.from_iterable(zip(*a))            # Python 3.x
5 голосов
/ 07 января 2012

Рецепт itertools roundrobin () был бы моим первым выбором, хотя в вашем точном примере он будет производить бесконечную последовательность, поскольку он останавливается на самой длинной итерируемой, а не самой короткой. Конечно, это было бы легко исправить. Может быть, стоит попробовать другой подход?

...