我该如何计算笛卡尔乘积反复?笛卡尔、乘积、我该

2023-09-10 22:56:58 作者:可念不可说

这个问题的询问如何计算矢量的给定数量的笛卡儿积。因为矢量的数目是预先已知的和相当小的,该解决方案很容易与嵌套获得循环

This question asks how to compute the Cartesian product of a given number of vectors. Since the number of vectors is known in advance and rather small, the solution is easily obtained with nested for loops.

现在假设你被赋予,在你选择的语言,向量的向量(列表或列表,或一组套等。):

Now suppose that you are given, in your language of choice, a vector of vectors (or list of lists, or set of sets, etc.):

l = [ [1,2,3], [4,5], [6,7], [8,9,10], [11,12], [13] ]

如果有人问我计算它的笛卡尔乘积,也就是

If I was asked to compute its Cartesian product, that is

[ [1,4,6,8,11,13], [1,4,6,8,12,13], [1,4,6,9,11,13], [1,4,6,9,12,13], ... ]

我会继续递归。例如,在快速和放脏蟒蛇,

I would proceed with recursion. For example, in quick&dirty python,

def cartesianProduct(aListOfLists):
    if not aListOfLists:
        yield []
    else:
        for item in aListOfLists[0]:
            for product in cartesianProduct(aListOfLists[1:]):
                yield [item] + product

有没有一种简单的方法来计算它的迭代吗?

(注:答案并不需要在蟒蛇,反正我知道,在Python itertools做的工作做得更好,在this问题。)

(Note: The answer doesn't need to be in python, and anyway I'm aware that in python itertools does the job better, as in this question.)

推荐答案

1)创建索引列表到相应的列表,初始化为0,即:

1) Create a list of indexes into the respective lists, initialized to 0, i.e:

indexes = [0,0,0,0,0,0]

2)从每个列表(在这种情况下,第一)收率适当的元素

2) Yield the appropriate element from each list (in this case the first).

3)加一的最后一个索引。

3) Increase the last index by one.

4)如果最后一个指标等于最后名单的长短,其重置为零,并携带一个。重复此之前一直没有随身携带。

4) If the last index equals the length of the last list, reset it to zero and carry one. Repeat this until there is no carry.

5)回到步骤2,直到指标转回到[0,0,0,0,0,0]

5) Go back to step 2 until the indexes wrap back to [0,0,0,0,0,0]

它类似于如何计数正常工作,不过基每个数位可以是不同的。

It's similar to how counting works, except the base for each digit can be different.

下面是上述算法在Python的实现:

Here's an implementation of the above algorithm in Python:

def cartesian_product(aListOfList):
    indexes = [0] * len(aListOfList)
    while True:
        yield [l[i] for l,i in zip(aListOfList, indexes)]
        j = len(indexes) - 1
        while True:
            indexes[j] += 1
            if indexes[j] < len(aListOfList[j]): break
            indexes[j] = 0
            j -= 1
            if j < 0: return

下面是另一种方式使用模技巧来实现:

Here is another way to implement it using modulo tricks:

def cartesian_product(aListOfList):
    i = 0
    while True:
        result = []
        j = i
        for l in aListOfList:
             result.append(l[j % len(l)])
             j /= len(l)
        if j > 0: return
        yield result
        i += 1

请注意,此输出的结果稍有不同的顺序,比在你的榜样。这可以通过固定遍历以相反的顺序列表。

Note that this outputs the results in a slightly different order than in your example. This can be fixed by iterating over the lists in reverse order.