执行 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
返回一个迭代器,它将生成A
和B
的笛卡尔积;例如
>>> 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=2
和A
和B
给出
>>> 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
重复A
和n_B
重复B
的笛卡尔积,其中n_A
和n_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)
或 A
和 B
的其他顺序?我想从技术上讲这会改变产品,因为它们的顺序不同,但是我会对产品进行分类,所以这并不重要。
这就是我问的部分原因,是的。另一个原因是因为 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 允许不同迭代次数的不同重复的主要内容,如果未能解决你的问题,请参考以下文章