将范围向量转换为 Python 中的集合组合

Converting a vector of ranges into combination of sets in Python

在 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) 开始?

要获得笛卡尔积,请执行以下操作:

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)

您可以使用内置的 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)]