2017-07-20 7 views
1

ジェネレータの製品に対して、対角を除いて繰り返し処理する必要があります。単一のiterableからジェネレータの製品そのもの

戻りn個の独立したイテレータ:私は二回

def pairs_exclude_diagonal(it): 
    i1, i2 = itertools.tee(it, 2) 
    for x in i1: 
     for y in i2: 
      if x != y: 
       yield (x, y) 

これは

In [1]: for (x, y) in pairs_exclude_diagonal(range(3)): 
    ...:  print(x, y) 
0 1 
0 2 

documentation for tee状態を動作しません同じジェネレータを消費するitertools.teeを使用しようとしています。

これを行うには適切な方法はありますか?

(私はpython3.6.1を使用しています)

答えて

1

問題は、i2イテレータを再利用しようとしているということです。それが一度反復された後、それは疲れているので、あなたは再びそれを反復することができません。試してみると何も得られません。

私は(ものをフィルタリングする前にスキップする)(いずれにせよ、この目的のために非常に効率的ではないです)、あなたはすべてのペアを生成するためにitertools.productを使用すべきではなくteeより考える:

def pairs_exclude_diagonal(it): 
    for x, y in itertools.product(it, repeat=2): 
     if x != y: 
      yield (x, y) 
+0

私は何とか私が「製品」を試してみたのと同じ問題を抱えていたことが私の頭の中にありました。ちょうど試してみて、うまく動作します。 DoH。 –

+0

また、もちろんit2を2度使用しています。それを指摘してくれてありがとう。 –

+0

'product'に' repeat = 2'を使わない限り、このレシピのアンパックエラーが出ます。これはあなたのためのものですか? – SethMMorton

4

に見えますあなたはitertools.permutationsを使いたいと思っています。

In [1]: import itertools 

In [2]: for x, y in itertools.permutations(range(3), 2): 
    ...:  print(x, y) 
    ...:  
0 1 
0 2 
1 0 
1 2 
2 0 
2 1 

あなた本当には、あなたがそれを外forループを介して第2の時間に排出されないようにlistに第二のiterableをオンにする必要があります、teeを使用して、それをしたい場合:

In [14]: def pairs_exclude_diagonal(it): 
    ...:  i1, i2 = itertools.tee(it, 2) 
    ...:  l2 = list(i2) 
    ...:  for x in i1: 
    ...:   for y in l2: 
    ...:    if x != y: 
    ...:     yield (x, y) 
    ...:     

In [15]: for (x, y) in pairs_exclude_diagonal(range(3)): 
    ...:  print(x, y) 
    ...:  
0 1 
0 2 
1 0 
1 2 
2 0 
2 1 

イテレータでlistを呼び出すと、それがメモリにロードされ、最初にイテレータを持つ目的が無効になるため、これはかなり意味がないことに注意してください。

+1

この回答は私のものより少し優れています(私の解決策ではなく、質問者のコードに関する問題の説明については続きます)。あなたの 'tee'ソリューションはかなり無意味だと言いたいと思います。イテレータの1つで 'list'を呼び出す場合は、' it'引数を直接呼び出して両方のループに使用することもできます。 – Blckknght

+1

@Blckknght私は100%が 'tee'解決策が無意味であることに同意します。私はそれを説明することを考えた...しかし、私はしなかった。私は今それについて少し追加します。 – SethMMorton