克隆笛卡尔积的生成器,无需重复

问题描述 投票:3回答:2

我有一个生成器,我想在它上面执行一个嵌套循环,使得内循环将从外循环所在的位置开始。例如,我有一个生成列表[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代码的任何建议吗?

python cartesian-product
2个回答
3
投票

仅重复克隆和排出所得到的一个迭代器并不是非常有效。根据itertools.tee docs

通常,如果一个迭代器在另一个迭代器启动之前使用大部分或全部数据,则使用list()而不是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)

0
投票

结果(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)
© www.soinside.com 2019 - 2024. All rights reserved.