2017-05-01 12 views
0

私は組み合わせのペアを反復しようとしています。私は、概念や実用的な観点の両方から、これを行うためのより良い方法を考え出したがなぜループは(ティーと一緒に)、このように振る舞うのか?

、これが私の最初の衝動だったし、それが機能しなかった理由を私は思ったんだけど。

gen = itertools.combinations(range(1, 6), 3) 
for i in gen: 
    gen, gencopy = itertools.tee(gen) 
    for j in gencopy: 
    print(i, j) 

は、以下の出力を与える:

(1、2、3)(1、2、4)
(1、2、3)(1、2、5)
(1,2,3)(1,3,4)
(1,3,5)
(1,2,3)(1,4,5)
(1、2、3) 、2、3)(2、3、4)
(1、2、3)(2、3、5)
(1、2、3) (2、4、5)
(1、2、3)(3、4、5)

i Sの一方のみを横切って反復されることを意味します。私はteeラインを変更した場合

は、しかし:

_, gencopy = itertools.tee(gen) 

私が期待されるペアのフルセットを取得します。

(注:これを実行する最善の方法は、組み合わせのペアを取得し、teeで提示されたパフォーマンスの問題を避けるために、itertools.combinationsを通してジェネレータに戻すことです。私は、forループの振る舞いと、このように発電機を変えるなぜそれが早期に救済する原因となっている程度興味)documentationから

+0

のpython 3.4:あなたが投稿1:私は同じ出力のいずれかの方法を取得。 –

+0

docsから "一度t​​ee()が分割されると、元のiterableは他の場所では使用しないでください。そうでなければ、teeオブジェクトに通知されずにiterableを進めることができます。だからあなたのコードはいずれかの方法で間違っています。 –

+0

奇数、私はPython 3.6.0を使用しています – OmnipotentEntity

答えて

1

:ティー一度

()分割をしました、元のiterableは他の場所では使用しないでください。さもなければ、iterableはteeオブジェクトに通知されることなく進歩する可能性があります。

出力に1回の以上の反復子を使用して反復子間でオブジェクトを共有することであるteeの思想(それぞれには、元のリストを「消費」されます)。

このitertoolには、(一時的なデータを格納する必要があるかどうかによって)かなりの補助記憶領域が必要な場合があります。別のイテレータを開始する前に1つのイテレータがほとんどまたはすべてのデータを使用する場合、一般的に、(リストを使用する方が速い)の代わりにティーの()。

正確には、内部ループはすべてのデータを消費し、外側ループは一度に終了します。ドキュメントが示唆

回避策:あなたは最初から発電機の機能を「殺す」以来

gen = list(itertools.combinations(range(1, 6), 3)) 
for i in gen: 
    for j in gen: 
    print(i, j) 

もちろん、これは、高いメモリフットプリントを有することができます。ですから、二重ループの代わりに組み合わせを使用するという考えは、おそらく最高です。

関連するQ & A:How to clone a Python generator object?

関連する問題