2012-01-07 5 views
13

私はitertoolsが(それは私には思える)他のいくつかの反復可能なオブジェクト(それらをビュンとは反対に)からインターリーブ要素のできる機能を持っていないことに気づいた:Pythonには、ジェネレータ/シーケンスをインターリーブするための組み込み関数がありますか?

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)) 
+6

全く関係のない注記では、私は問題のバッハがジョンではなくヨハンであると言及しています。 – 9000

+0

@ 9000:確かに、これは単なるテストではありませんでしたが、私はそのままそれを書きました – Marcin

答えて

4

itertools、最短ではない。もちろん、それを修正するのは簡単でしょう。たぶん別のアプローチをチェックアウトする価値がありますか?

+0

それは私が思っていたことですが、(a)私は葉のセマンティクスを好む(b)私の定義はより簡潔です。 – Marcin

9

あなたは組み込みのzipitertools.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のための代替の実装は次のようになります。それは最長の反復可能で停止してあなたの正確な例では、それは、無限のシーケンスを生成するのにroundrobin() recipeは、私の最初の選択肢となっていただろう

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 
+0

'izip'は安全でしょうか? –

+0

@larsmansどのように安全ですか? 'itertools.izip'は3.0からPythonから削除されました。 – phihag

+1

私はまだPython 2.xの世界に住んでいます。 –

関連する問題