我有一组数组,例如
["a1", "a2"]
["b1", "b2", "b3"]
["c1", "c2"]
["d1", "d2", "d3", "d4"]
可以有任何数量的这些数组。 使用第一个数组,有一种很好的方法可以循环记录每个组合的其他数组。
例如
a1,b1,c1,d1
a2,b1,c1,d1
a1,b2,c1,d1
a2,b2,c1,d1
.
.
.
a1,b1,c1,d4
a2,b1,c1,d4
.
.
.
a1,b3,c2,d4
a2,b3,c2,d4
我正在尝试绘制概率树的结果,这部分让我陷入困境
答案 0 :(得分:4)
对于未指定数量的数组,您可以这样做:
var arrays = [
["a1", "a2"],
["b1", "b2", "b3"],
["c1", "c2"],
["d1", "d2", "d3", "d4"]
];
(function dive(stack) {
if (stack.length==arrays.length) {
console.log(stack);
} else {
arrays[stack.length].forEach(function(v){
dive(stack.concat(v));
});
}
})([]);
Demonstration(打开控制台)
如果您想支持旧浏览器,请使用a shim for forEach。
答案 1 :(得分:4)
鉴于我理解你的问题是正确的,你是在所有子阵列的Cartesian product之后。
让我们从构建最笨的版本开始吧;没有聪明,只是一个双循环:
function product ( left, right ) {
var ret = [];
for (var i = 0; i < left.length; i++) {
for (var j = 0; j < right.length; j++) {
ret.push( [left[i], right[j]] );
}
}
return ret;
}
我们只是按照产品的定义:left
中的每个项目都对right
中的每个项目。让我们把它搞砸一下:我们迭代两个数组,将每个左项映射到右项。也许如果我们使用Array#map
...
function product ( left, right ) {
return left.map(function ( i ) {
return right.map(function ( j ) {
return [i, j];
});
});
}
但是,这会创建一个嵌套数组:
> product( [0, 1], [2, 3] );
[ [[0,2], [0,3]],
[[1,2], [1,3]] ]
我们可以通过减少第一个数组来解决这个问题:
function product ( left, right ) {
return left.reduce(function ( ret, i ) {
var ans = right.map(function ( j ) {
return [i, j];
});
return ret.concat( ans );
}, []);
}
到目前为止,这描述了产品left × right
,但您想要一个n-ary产品:A × B × C × ...
我们将如何做到这一点?
我们将使用笛卡尔积的一个非常有用的特征:A × B × C = A × (B × C)
。这意味着我们可以递归地定义n-ary产品。这是第一次尝试:
function product ( left, right, other ) {
if ( other ) {
right = product.apply( this, [].slice.call(arguments, 1) );
}
return left.reduce(function ( ret, i ) {
var ans = right.map(function ( j ) {
return [i, j];
});
return ret.concat( ans );
}, []);
}
错误应该清楚:[i, j]
。假设我们实际上有一个标量和一个数组,我们假设我们有两个标量(常规值,平坦值)。修复很容易:我们不是将结果包装在数组中,而是将数组连接到标量,从而得到最终的解决方案:
function product ( left, right, other ) {
if ( other ) {
right = product.apply( this, [].slice.call(arguments, 1) );
}
return left.reduce(function ( ret, i ) {
var ans = right.map(function ( j ) {
return [i].concat( j );
});
return ret.concat( ans );
}, []);
}
在你的情况下,由于你有一个数组数组,在调用时,你需要将它展平:
> var arr = [ ["a1", "a2"], ["b1", "b2", "b3"], ["c1", "c2"], ["d1", "d2", "d3", "d4"] ];
undefined
> product.apply( null, arr );
[ [ 'a1', 'b1', 'c1', 'd1' ],
[ 'a1', 'b1', 'c1', 'd2' ],
[ 'a1', 'b1', 'c1', 'd3' ],
[ 'a1', 'b1', 'c1', 'd4' ],
[ 'a1', 'b1', 'c2', 'd1' ],
[ 'a1', 'b1', 'c2', 'd2' ],
[ 'a1', 'b1', 'c2', 'd3' ],
[ 'a1', 'b1', 'c2', 'd4' ],
[ 'a1', 'b2', 'c1', 'd1' ],
[ 'a1', 'b2', 'c1', 'd2' ],
[ 'a1', 'b2', 'c1', 'd3' ],
[ 'a1', 'b2', 'c1', 'd4' ],
[ 'a1', 'b2', 'c2', 'd1' ],
[ 'a1', 'b2', 'c2', 'd2' ],
[ 'a1', 'b2', 'c2', 'd3' ],
[ 'a1', 'b2', 'c2', 'd4' ],
[ 'a1', 'b3', 'c1', 'd1' ],
[ 'a1', 'b3', 'c1', 'd2' ],
[ 'a1', 'b3', 'c1', 'd3' ],
[ 'a1', 'b3', 'c1', 'd4' ],
[ 'a1', 'b3', 'c2', 'd1' ],
[ 'a1', 'b3', 'c2', 'd2' ],
[ 'a1', 'b3', 'c2', 'd3' ],
[ 'a1', 'b3', 'c2', 'd4' ],
[ 'a2', 'b1', 'c1', 'd1' ],
[ 'a2', 'b1', 'c1', 'd2' ],
[ 'a2', 'b1', 'c1', 'd3' ],
[ 'a2', 'b1', 'c1', 'd4' ],
[ 'a2', 'b1', 'c2', 'd1' ],
[ 'a2', 'b1', 'c2', 'd2' ],
[ 'a2', 'b1', 'c2', 'd3' ],
[ 'a2', 'b1', 'c2', 'd4' ],
[ 'a2', 'b2', 'c1', 'd1' ],
[ 'a2', 'b2', 'c1', 'd2' ],
[ 'a2', 'b2', 'c1', 'd3' ],
[ 'a2', 'b2', 'c1', 'd4' ],
[ 'a2', 'b2', 'c2', 'd1' ],
[ 'a2', 'b2', 'c2', 'd2' ],
[ 'a2', 'b2', 'c2', 'd3' ],
[ 'a2', 'b2', 'c2', 'd4' ],
[ 'a2', 'b3', 'c1', 'd1' ],
[ 'a2', 'b3', 'c1', 'd2' ],
[ 'a2', 'b3', 'c1', 'd3' ],
[ 'a2', 'b3', 'c1', 'd4' ],
[ 'a2', 'b3', 'c2', 'd1' ],
[ 'a2', 'b3', 'c2', 'd2' ],
[ 'a2', 'b3', 'c2', 'd3' ],
[ 'a2', 'b3', 'c2', 'd4' ] ]