您如何生成多个数组的所有可能结果? [重复]

问题描述 投票:0回答:1

我需要生成多个数组的所有可能组合。

例如,如果我有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...

实现此目标的最佳方法是什么?

javascript arrays math combinations permutation
1个回答
0
投票

您实际上有三个要迭代的维度。所以像这样的事情会做的。但是未经测试的代码。只是写下来,这样您就可以感觉到您要做的事情。

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);
    }
  }
}

也许有更好的方法,但这是可靠的方法。


2
投票

编辑:我已经比较了使用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]

然后您可以选择处理。

© www.soinside.com 2019 - 2024. All rights reserved.