执行 itertools.product 允许不同迭代次数的不同重复

Posted

技术标签:

【中文标题】执行 itertools.product 允许不同迭代次数的不同重复【英文标题】:Carry out itertools.product allowing for a different number of repetitions for different iterables 【发布时间】:2022-01-23 20:21:27 【问题描述】:

假设我有两个迭代 A = 'ab'B = '12'

itertools.product 返回一个迭代器,它将生成AB 的笛卡尔积;例如

>>> list(itertools.product(A,B)) 
[('a', '1'), ('a', '2'), ('b', '1'), ('b', '2')].

该函数有一个可选的关键字参数repeat,可用于查找一个可迭代对象与自身的笛卡尔积;例如

>>> list(itertools.product(A,repeat=2))
[('a', 'a'), ('a', 'b'), ('b', 'a'), ('b', 'b')]

相当于list(itertools.product(A,A))

然后使用repeat=2AB 给出

>>> list(itertools.product(A,B,repeat=2))
[('a', '1', 'a', '1'), ('a', '1', 'a', '2'), ('a', '1', 'b', '1'), ('a', '1', 'b', '2'), ('a', '2', 'a', '1'), ('a', '2', 'a', '2'), ('a', '2', 'b', '1'), ('a', '2', 'b', '2'), ('b', '1', 'a', '1'), ('b', '1', 'a', '2'), ('b', '1', 'b', '1'), ('b', '1', 'b', '2'), ('b', '2', 'a', '1'), ('b', '2', 'a', '2'), ('b', '2', 'b', '1'), ('b', '2', 'b', '2')]

相当于list(itertools.product(A,B,A,B))

但是现在假设我想找到n_A 重复An_B 重复B 的笛卡尔积,其中n_An_B 不必相同。我怎样才能做到这一点?如果repeat 得到元组(n_A, n_B) 我可以写就好了

list(itertools.product(A,B,repeat=(n_A,n_B)))

例如

list(itertools.product(A,B,repeat=(2,3))) == list(itertools.product(A,A,B,B,B))

但这似乎是不允许的。

注意,(A,A,B,B,B)(A,B,A,B,B) 是不同的产品,但无论如何我都会对输出进行排序,所以我不关心输入的顺序。

【问题讨论】:

product(A,B,repeat=(2,3)) 应该等价于什么(没有repeat 参数)? 你指的是重复的顺序吗? IE。 product(A,A,B,B,B)product(A,B,A,B,B)AB 的其他顺序?我想从技术上讲这会改变产品,因为它们的顺序不同,但是我会对产品进行分类,所以这并不重要。 这就是我问的部分原因,是的。另一个原因是因为 Adam 的回答做了类似 product(A*2,B*3) 的操作,产生 2 元组而不是 5 元组。 既然我正在对产品进行分类(这会产生重复的结果),也许我根本不是在寻找产品,而是在寻找组合? 【参考方案1】:

使用tee“复制”每个可迭代对象,然后将它们展平为单个参数列表,并使用 * 解包将它们作为单独的参数传递给产品

from itertools import product, chain, tee

def myproduct(*iterables, repeat=1):
    if isinstance(repeat, int):
        return product(iterables, repeat)
    assert isinstance(repeat, tuple)
    args = chain(*map(tee, iterables, repeat))
    return product(*args)


A = 'ab'
B = '12'

n_A = 2
n_B = 3


result = list(product(A, A, B, B, B))
result2 = list(myproduct(A, B, repeat=(n_A, n_B)))

print(result == result2)

【讨论】:

len 不适用于所有可迭代对象。 chain.from_iterable(tee(iterable, count)) 应该适用于任何迭代器(并且启动时间更短)。 @chepner 好样的!测试和编辑:) 是的,请参阅凯利对问题的评论和我的编辑以进行澄清。我认为使用tee 是正确的想法。类似于product(tee(A,n_A), tee(B,n_B)),但这给出了tee 对象的列表。 短一点:args = chain(*map(tee, iterables, repeat))

以上是关于执行 itertools.product 允许不同迭代次数的不同重复的主要内容,如果未能解决你的问题,请参考以下文章

Python itertools.product 具有任意数量的集合

Python的itertools.product 方法

itertools.product 比嵌套 for 循环慢

itertools.product - 返回列表而不是元组

itertools.product 消除重复元素

Itertools.product 自定义每个输入的组合数量?