我需要生成多个数组的所有可能组合。
例如,如果我有3个不同的数组,如下所示:
var size = ["x-small", "small", "medium", "large", "x-large"];
var color = ["red", "blue", "green", "yellow"];
var material = ["plastic", "metal", "wood"];
而且我想产生以下结果:
[{size: "x-small", color: "red", material: "plastic"},
{size: "x-small", color: "red", material: "metal"},
{size: "x-small", color: "red", material: "wood"},
{size: "x-small", color: "blue", material: "plastic"},
{size: "x-small", color: "blue", material: "metal"},
{size: "x-small", color: "blue", material: "wood"}]
etc...
实现此目标的最佳方法是什么?
您实际上有三个要迭代的维度。所以像这样的事情会做的。但是未经测试的代码。只是写下来,这样您就可以感觉到您要做的事情。
var array = [];
var size = ["x-small", "small", "medium", "large", "x-large"];
var color = ["red", "blue", "green", "yellow"];
var material = ["plastic", "metal", "wood"];
for(var i = 0; i < size.length; i++) {
for(var j = 0; j < color.length; j++) {
for(var k = 0; k < material.length; k++) {
var hObj = {};
hObj['size'] = size[i];
hObj['color'] = color[j];
hObj['material'] = material[k];
array.push(hObj);
}
}
}
也许有更好的方法,但这是可靠的方法。
编辑:我已经比较了使用jsperf here的不同方法,显然Phrogz的方法是最快的,是此处第三种方法的两倍。
如果我的理解正确,您是在询问有关计算数字的每一列是不同基数的地方。您可以递归执行此操作。
function options(opArr, fullArray){
var i = 0, j = opArr.length;
if(j < fullArray.length){ // if opArr doesn't have item from each group, add new group
while(i < fullArray[j]){ // count up for this group
newArr = opArr.slice(0); // clone opArr so we don't run into shared reference troubles, not sure if necessary
newArr[j] = i;
i++;
options(newArr, fullArray); // recurse
}
}else{ // opArr is now a unique array of your items
// console.log(opArr);
}
}
options([], [3, 9, 3, 3]);
注意:此(示例)将导致生成3 * 9 * 3 * 3 = 243
阵列。这样您可能会吃很多内存。
[另一种方法是将整数转换为数组,这可能会节省内存使用,因为您会忘记所有先前计算的数组
function countUp(arrayOfBases, callback, self){
var arr = arrayOfBases.reverse(), x = 1, i = arr.length,
me = (self===undefined?this:self),
makeArr = function(arr, x, fn, me){
var a = arr.slice(0), n = [], i = x, j = 0, k = 0;
while(a.length > 0){
k = a[0];
if(k !== 0) j = i % k, i = (i - j) / k;
else j = 0;
n.unshift(j);
a.shift();
}
fn.call(me,n);
};
while (i-->0) if(arr[i] !== 0) x = x * arr[i];
i = 0;
while(i < x){
makeArr(arr, i, callback, me);
i++;
}
}
countUp([3,9,3,3], function(a){console.log(a);});
[与以前类似的另一种方法,保留了上次生成的数组,因此循环中的计算较少,但要花更多的时间来初始化。
function countUp2(arrayOfBases, callback, self){
var arr = arrayOfBases.reverse(), x = 1, i = arr.length, last = [],
me = (self===undefined?this:self),
addOne = function(arr, n, fn, me){
var j = n.length, i = j - 1;
n[i]++;
while(j = i, i-- > 0 && n[j] >= arr[j]){
if(arr[j] === 0) n[i] += n[j], n[j] = 0;
else n[i]++, n[j] -= arr[j];
}
return fn.call(me,n.slice(0)), n;
};
while (i-->0){
if(arr[i] !== 0) x = x * arr[i];
last[i] = 0;
}
i = 0;
last[last.length-1] = -1;
while(i < x){
last = addOne(arr, last, callback, me);
i++;
}
}
countUp2([3,9,3,3], function(a){console.log(a);});
将输出所有这些方法
[0,0,0,0]
[0,0,0,1]
...
[0,8,1,2]
[0,8,2,0]
...
[2,8,2,1]
[2,8,2,2]
然后您可以选择处理。