克隆笛卡尔积的生成器而不重复
Cloning a generator for Cartesian product without duplications
我有一个生成器,我想对其执行嵌套循环,使内循环将从外循环所在的位置开始。
例如,我有一个生成列表 [1,2,3]
的生成器,我的循环应该生成:(1,2),(1,3),(2,3)
。
我想出的代码如下:
from itertools import tee
def my_gen():
my_list = [1, 2, 3]
for x in my_list:
yield x
first_it = my_gen()
while True:
try:
a = next(first_it)
first_it, second_it = tee(first_it)
for b in second_it:
print(a,b)
except StopIteration:
break
这段代码很麻烦,效率不高,而且在我看来也不是很pythonic。请注意我不能使用 combinations_with_replacement
因为我需要一个内部循环来处理来自外部循环的特定值。
对更优雅和 pythonic 代码有什么建议吗?
仅对其中一个生成的迭代器进行重复克隆和耗尽,效率不高。根据 itertools.tee
docs:
In general, if one iterator uses most or all of the data before another iterator starts, it is faster to use list() instead of tee().
from itertools import islice
my_list = [1, 2, 3]
# or, more generally
# my_list = list(my_gen())
for i, a in enumerate(my_list):
for b in islice(my_list, i+1, None):
print((a, b))
(1, 2)
(1, 3)
(2, 3)
结果 (1,2),(1,3),(2,3)
不是笛卡尔积。你的意思是得到所有的组合不重复吗?
不重复的组合
使用itertools.combinations
函数:
from itertools import combinations
print(list(combinations([1,2,3], 2)))
实际笛卡尔积
使用列表理解,您可以将代码简化为更 pythonic 和优雅的方式:
my_list = [1, 2, 3]
c_prod = [(i, j) for i in iter(my_list) for j in iter(my_list)]
print(c_prod)
另一种选择是使用itertools.product
函数:
import itertools
for i in itertools.product(my_list, my_list):
print(i)
我有一个生成器,我想对其执行嵌套循环,使内循环将从外循环所在的位置开始。
例如,我有一个生成列表 [1,2,3]
的生成器,我的循环应该生成:(1,2),(1,3),(2,3)
。
我想出的代码如下:
from itertools import tee
def my_gen():
my_list = [1, 2, 3]
for x in my_list:
yield x
first_it = my_gen()
while True:
try:
a = next(first_it)
first_it, second_it = tee(first_it)
for b in second_it:
print(a,b)
except StopIteration:
break
这段代码很麻烦,效率不高,而且在我看来也不是很pythonic。请注意我不能使用 combinations_with_replacement
因为我需要一个内部循环来处理来自外部循环的特定值。
对更优雅和 pythonic 代码有什么建议吗?
仅对其中一个生成的迭代器进行重复克隆和耗尽,效率不高。根据 itertools.tee
docs:
In general, if one iterator uses most or all of the data before another iterator starts, it is faster to use list() instead of tee().
from itertools import islice
my_list = [1, 2, 3]
# or, more generally
# my_list = list(my_gen())
for i, a in enumerate(my_list):
for b in islice(my_list, i+1, None):
print((a, b))
(1, 2)
(1, 3)
(2, 3)
结果 (1,2),(1,3),(2,3)
不是笛卡尔积。你的意思是得到所有的组合不重复吗?
不重复的组合
使用itertools.combinations
函数:
from itertools import combinations
print(list(combinations([1,2,3], 2)))
实际笛卡尔积
使用列表理解,您可以将代码简化为更 pythonic 和优雅的方式:
my_list = [1, 2, 3]
c_prod = [(i, j) for i in iter(my_list) for j in iter(my_list)]
print(c_prod)
另一种选择是使用itertools.product
函数:
import itertools
for i in itertools.product(my_list, my_list):
print(i)