我需要迭代生成器的产品,不包括对角线。我尝试使用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
从单个可迭代中返回n个独立迭代器。
这样做的正确方法是什么?
(我使用的是python3.6.1)
答案 0 :(得分: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 :(得分: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)