This question询问如何计算给定数量向量的笛卡尔乘积。由于向量的数量是预先知道的并且相当小,因此使用嵌套的for循环很容易获得解决方案。
现在假设您以您选择的语言给出了矢量向量(或列表列表或集合等):
l = [ [1,2,3], [4,5], [6,7], [8,9,10], [11,12], [13] ]
如果我被要求计算其笛卡尔积,那就是
[ [1,4,6,8,11,13], [1,4,6,8,12,13], [1,4,6,9,11,13], [1,4,6,9,12,13], ... ]
我会继续进行递归。例如,在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中,无论如何我都知道在python中,itertools可以更好地完成工作,就像this question一样。)
答案 0 :(得分:16)
1)在各自的列表中创建一个索引列表,初始化为0,即:
indexes = [0,0,0,0,0,0]
2)从每个列表中产生适当的元素(在这种情况下是第一个)。
3)将最后一个索引增加一个。
4)如果最后一个索引等于最后一个列表的长度,则将其重置为零并携带一个。重复此操作,直到没有进位。
5)返回步骤2,直到索引回到[0,0,0,0,0,0]
它类似于计数的工作原理,除了每个数字的基数可以不同。
以下是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
以下是使用模数技巧实现它的另一种方法:
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
请注意,这会以与示例中略有不同的顺序输出结果。这可以通过以相反的顺序迭代列表来解决。
答案 1 :(得分:2)
对于所有\Pi a_i_length
,从0到i
迭代。
for ( int i = 0; i < product; i++ ) {
// N is the number of lists
int now = i;
for ( int j = 0; j < N; j++ ) {
// This is actually the index, you can get the value easily.
current_list[j] = now % master_list[j].length;
// shifts digit (integer division)
now /= master_list[j].length;
}
}
还有一些简单的方法来写这个,所以你不必两次做同样的工作。
答案 2 :(得分:2)
既然你要求一个与语言无关的解决方案,这里有一个bash,但我们可以称之为迭代,递归,它是什么?这只是表示法:
echo {1,2,3},{4,5},{6,7},{8,9,10},{11,12},13
也许有趣。
1,4,6,8,11,13 1,4,6,8,12,13 1,4,6,9,11,13 1,4,6,9,12,13 1,4,6,10,11,13 ...
答案 3 :(得分:1)
您只需手动管理堆栈。基本上,做你自己的递归。由于递归将关于每个递归调用的数据放在堆栈上,您只需执行相同的操作:
Let L[i] = elements in vector i
k = 0;
st[] = a pseudo-stack initialized with 0
N = number of vectors
while ( k > -1 )
{
if ( k == N ) // solution, print st and --k
if ( st[k] < L[k].count )
{
++st[k]
++k
}
else
{
st[k] = 0;
--k;
}
}
未经测试,但这个想法会奏效。希望我没有错过任何东西。
编辑:好吧,我猜太晚了。这与计算基本相同,只是另一种看待它的方式。