在Python中,我有一个这样的范围列表:
A = [range(0,2),range(0,4),range(0,3),range(0,3)]
首先我必须把所有这些范围转换成集合。我可以创建一个空集合,并将结果列表添加到其中。我会写:
B = [[0, 1], [0, 1, 2, 3], [0, 1, 2], [0, 1, 2]]
但是在那之后,我必须创建列表之间所有可能的元素组合。最小值的集合是[0,0,0,0],最大值是:[1,3,2,2]。它是2x4x3x3 = 72组的组合。我如何实现这个结果,从范围列表(A)开始?
您可以使用内置的itertools
模块取A
中所有range
对象的笛卡尔积,而完全跳过制作B
:
import itertools
A = [range(2), range(4), range(3), range(3)]
list(itertools.product(*A))
输出(为了便于阅读,省略了一些项目):
[(0, 0, 0, 0),
(0, 0, 0, 1),
(0, 0, 0, 2),
(0, 0, 1, 0),
(0, 0, 1, 1),
.
.
.
(1, 3, 2, 2)]
验证长度:
>>> len(list(itertools.product(*A)))
72
注意itertools.product()
产生tuple
对象。如果出于某种原因,您希望这些是列表,则可以使用推导式:
[[*p] for p in itertools.product(*A)]
另一种方法,正如@don'ttalkjustcode所指出的,是您可以完全避免创建A
,并通过map()
函数直接跳转到笛卡尔积:
list(itertools.product(*map(range, (2, 4, 3, 3))))
但是,这里假设所有的范围都从0开始。
您可以使用lambda
来推广这种映射技术,它将从元组列表中创建范围对象:
>>> list(map(lambda t: range(*t), ((6, -3, -1), (0, 3), (5,), (10, 1, -2))))
[range(6, -3, -1), range(0, 3), range(0, 5), range(10, 1, -2)]
要得到笛卡尔积,请执行以下操作:
A = []
for i in range(2):
for j in range(4):
for k in range(3):
for n in range(3):
combo = [i,j,k,n]
A.append(combo)