2017-07-20 56 views
1

我需要迭代發電機與自身的乘積,不包括對角線。我試圖用itertools.tee消耗相同的發電機兩次發電機本身的產品

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狀態:從單一的迭代

返回n個獨立的迭代器。

這樣做的正確方法是什麼?

(我使用python3.6.1)

回答

1

的問題是,你想重用i2迭代器。迭代一次後,它已經耗盡,所以你將無法再次迭代它。當你嘗試時,它什麼都沒有。

我想,而不是tee(這是不是爲了這個目的反正非常有效的),你應該使用itertools.product生成所有對(過濾掉你想跳過那些前):

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

我不知何故把它放在我的腦海裏,我試過'product',它有同樣的問題。剛剛嘗試過,它工作得很好。衛生部。 –

+0

另外,當然在使用'it2'兩次。感謝您指出了這一點。 –

+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 

如果你真的想用tee它做,你將不得不把第二迭代爲list,使其不通過外for循環耗盡在第二時間:

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'解決方案雖然沒有意義。如果你打算在其中一個迭代器上調用'list',那麼你可以直接在'it'參數上調用它並將它用於兩個循環。 – Blckknght

+1

@Blckknght我100%同意'tee'解決方案毫無意義。我想過解釋這個......但後來我沒有。現在我會補充一點。 – SethMMorton