【问题标题】:issue with extracting combination of values from multiple nested arrays从多个嵌套数组中提取值组合的问题
【发布时间】:2018-11-15 12:16:03
【问题描述】:

尝试遍历多个嵌套数组以获取新数组中可能值的每一个组合。

示例:

[
  ['a1', 'a2'],
  ['b1', 'b2'],
  ['c1', 'c2']
]

输出:

[
   ['a1'],
   ['a2'],
   ['b1'],
   ['b2'],
   ['c1'],
   ['c2'],
   ['a1', 'b1'],
   ['a1', 'b2'],
   ['a1', 'c1'],
   ['a1', 'c2'],
   ['a2', 'b1'],
   ['a2', 'b2'],
   ['a2', 'c1'],
   ['a2', 'c2'],
   ['b1', 'c1'],
   ['b1', 'c2'],
   ['b2', 'c1'],
   ['b2', 'c2']
]

知道如何实现这一点,也许我首先需要拆分数组?

【问题讨论】:

  • 您想要每个单个组合还是只需要其中包含 1 个和 2 个元素的组合?
  • 我认为您应该 1. 发布您编写的任何代码尝试,然后询问您遇到的特定问题,以及 2. 更详细地解释您的输入映射到该输出
  • 只是澄清一下:所以任何与 1..N 个成员的组合。
  • 你有 this similar question 但我没有标记为重复,因为我不确定我是否理解逻辑 - 为什么输出中的前 6 个元素是有效的,但不是 ['b1', 'a1']
  • 我需要和上面一样,不是所有的组合都像 ['a1', 'b1'] 和 ['b1', 'a1']

标签: javascript arrays


【解决方案1】:

您可以通过移交下一个索引并收集临时数组来采用递归方法。

function getCombinations(array, max) {

    function iter(i, j, temp) {
        if (array[i] && j >= array[i].length) {
            j = 0;
            i++;
        }
        if (!array[i] || temp.length === max) return;
        result.push(temp.concat(array[i][j]));
        iter(i + 1, 0, temp.concat(array[i][j]));
        iter(i, j + 1, temp);
    }

    var result = [];
    iter(0, 0, []);
    return result;
}

var array = [['a1', 'a2'], ['b1', 'b2'], ['c1', 'c2']],
    result = getCombinations(array, 2);

console.log(result.map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    您可以使用两个嵌套的 for 循环和一个参数来创建递归函数,以保持当前行迭代计数,以便您可以从那里开始下一个 for 循环。

    const data = [['a1', 'a2'], ['b1', 'b2'], ['c1', 'c2']]
    const res = []
    
    function comb(data, n = 0, prev = []) {
      for (var i = n; i < data.length; i++) {
        for (var j = 0; j < data[i].length; j++) {
          let el = data[i][j]
          let arr = prev.concat(el);
          if (arr.length <= data[i].length) res.push(arr)
          comb(data, i + 1, arr)
        }
      }
    }
    
    comb(data)
    console.log(JSON.stringify(res))

    【讨论】:

    • 嵌套循环的好主意。
    • @Nina Scholz 谢谢,不知道在不同数组长度的其他场景中是否能正常工作。
    • 我限制了最大值并退出递归。
    【解决方案3】:

    如果您也需要顺序(因此首先是单个元素,最后是对),也可以这样做,只是它会比其他解决方案长一点:

    var org=[['a1', 'a2'],['b1', 'b2'],['c1', 'c2']];
    
    var res=[];
    
    // singles
    org.forEach(arr => {
      arr.forEach(elem => {
        res.push([elem]);
      });
    });
    
    // pairs
    var start=0;
    var end=res.length;
    org.forEach(arr => {
      start+=arr.length;
      arr.forEach(elem => {
        for(var i=start;i<end;i++)
          res.push([elem,res[i][0]]);
      });
    });
    
    console.log(JSON.stringify(res));

    //singles 部分是一对嵌套循环,将所有元素推入,//pairs 再次遍历原始数组,只是利用了已经“扁平化”的结果,end 只是保持单个的数量元素(因为数组的长度会增加)并且start 总是跳转到下一个子数组的开头(因此不会生成类似'a1','a2' 的对,因为它是必需的)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-05
      • 1970-01-01
      • 2018-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多