【发布时间】:2020-10-06 14:57:49
【问题描述】:
如何在 Pyhton 中以优雅(简洁)的方式计算列表上的 n 倍笛卡尔积,即 A × ... × A(n 次)?
此问题与Get the cartesian product of a series of lists? 不重复。我不希望一系列列表的笛卡尔积相互交叉。我希望单个列表的笛卡尔积与自身交叉 n 次,其中 n 是给函数的参数。
例子:
l = ["a", "b", "c"]
> cart_prod(l, 0)
[]
> cart_prod(l, 1)
[('a',), ('b',), ('c',)]
> cart_prod(l, 2)
[('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'b'), ('b', 'c'), ('c', 'a'), ('c', 'b'), ('c', 'c')]
> cart_prod(l, 3)
[('a', 'a', 'a'), ('a', 'a', 'b'), ('a', 'a', 'c'), ('a', 'b', 'a'), ('a', 'b', 'b'), ('a', 'b', 'c'), ('a', 'c', 'a'), ('a', 'c', 'b'), ('a', 'c', 'c'), ('b', 'a', 'a'), ('b', 'a', 'b'), ('b', 'a', 'c'), ('b', 'b', 'a'), ('b', 'b', 'b'), ('b', 'b', 'c'), ('b', 'c', 'a'), ('b', 'c', 'b'), ('b', 'c', 'c'), ('c', 'a', 'a'), ('c', 'a', 'b'), ('c', 'a', 'c'), ('c', 'b', 'a'), ('c', 'b', 'b'), ('c', 'b', 'c'), ('c', 'c', 'a'), ('c', 'c', 'b'), ('c', 'c', 'c')]
我想出了以下迭代解决方案:
def cart_prod(l, n):
if n == 0:
return [] # compute the result for n = 0
# preliminarily, create a list of lists instead of a list of tuples
res = [[x] for x in l] # initialize list with singleton tuples (n = 1)
for i in range(n-1):
res = [r + [x] for r in res for x in l] # concatenate each n-1 tuple with each element from a
res = [tuple(el) for el in res] # turn the list of lists into a list of tuples
return res
这段代码可以完成这项工作,但是否有更短的、可能单行的定义,可能是嵌套列表理解或 lambda 表达式?我对更紧凑的解决方案感兴趣,不一定是更具可读性的解决方案。
【问题讨论】:
-
它在我看来仍然是重复的。只需复制列表,然后使用
itertools.product。 -
更好的是,
itertools.tee列表n次,然后使用itertools.product。 -
@bnaecker 你不需要
tee。 -
@chepner 不错,我以前从未使用过那个 kwarg。