【问题标题】:Matrix array algorithm logic in JavaScriptJavaScript中的矩阵数组算法逻辑
【发布时间】:2021-10-02 17:56:51
【问题描述】:

我正在尝试用 JavaScript 解决这个算法。考虑到最大键值为 3,如何编写考虑时间复杂度的解决方案?

input1 = [{0: "small"},{0: "large"}]
output1 = [ 'small.', 'large.']
-----------------------------------------
input2 = [ {0: "small"},{0: "large"}, {1: "red"} ]
output2 = ['small.red', 'large.red']
-----------------------------------------
input3 = [{0: "small"},{0: "large"}, {1: "red"}, {2:"cake"} ]
output3 = ['small.red.cake', 'large.red.cake'}
-----------------------------------------
input4 = [{0: "small"},{0: "large"}, {1: "red"}, {1: "orange"}, {2: "cake"} ]
output4 = ['small.red.cake', 'large.red.cake', 'small.orange.cake', 'large.orange.cake'}
------------------------------------------
input5 = [ {0: "small"},{0: "large"}, {1: "red"},{1: "orange"},{1: "blue"},{2: "cake"},{2: "ice"}]
output5 = ['small.red.cake', 'large.red.cake', 'small.orange.cake', 'large.orange.cake', 'small.blue.cake', 'large.blue.cake', 'small.red.ice', 'large.red.ice', 'small.orange.ice', 'large.orange.ice', 'small.blue.ice', 'large.blue.ice']
] //12 combinations

我的尝试:我故意在 if 条件下检查索引。它按预期工作。我正在寻找最佳解决方案。

const input5 = [ {0: "small"},{0: "large"}, {1: "red"},{1: "orange"},{1: "blue"},{2: "cake"},{2: "ice"}]

 let array1 = [];
let array2 = [];
let array3 = [];
input5.forEach(val => {
  if(val[0]) {
    array1.push(val[0]);
  }
  if(val[1]) {
    array2.push(val[1]);
  }
  if(val[2]) {
    array3.push(val[2]);
  }
});
const finalArray = [];
array1.forEach(val1 => {
  if(array2.length > 0) {
     array2.forEach(val2 => {
       if(array3.length > 0) {
         array3.forEach(val3 => {
           const finalVal = `${val1}.${val2}.${val3}`;
           finalArray.push(finalVal);
         })
       }else {
         const finalVal = `${val1}.${val2}`;
         finalArray.push(finalVal);
       }
     })
  }else {
    const finalVal = `${val1}.`;
    finalArray.push(finalVal);
  }
})
console.log(finalArray);

【问题讨论】:

  • 您有解决方案的尝试吗?将值除以级别/深度并在每个级别上进行排列基本上就是您所需要的。
  • 感谢@KelvinSchoofs 的回复,我长期以来一直在尝试使用 foreach 循环,但这不是正确的方法,也没有得到预期的结果。所以终于来到stackoverflow寻找解决方案。
  • 发布您的尝试仍然是个好主意。我们可以指出一个错误,或者如果您只是使用了错误的方法,我们可以建议另一种方法。
  • 我发布了我的尝试@KelvinSchoofs
  • 这感觉像是递归。

标签: javascript arrays object ecmascript-6 array-algorithms


【解决方案1】:

您可以使用所需索引处的值构建一个数组数组,并获得格式化后的笛卡尔积。

const
    cartesian = array => array.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), [])),
    format = array => {
        const temp = array.reduce((r, o) => {
            Object.entries(o).forEach(([i, v]) => (r[i] ??= []).push(v));
            return r;
        }, []);

        while (temp.length < 2) temp.push(['']);
        return temp;
    },
    fn = data => cartesian(format(data)).map(a => a.join('.'));

console.log(fn([{ 0: "small" },{ 0: "large" }]));
console.log(fn([{ 0: "small" }, { 0: "large" }, { 1: "red" }, { 1: "orange" }, { 2: "cake" }]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 感谢最短的解决方案,它适用于 input5 但不适用于 input1。我会修改它。欣赏。
  • @Trinu,如果数组中没有对象怎么办?请参阅编辑。
【解决方案2】:

这种方法可行,但它是否符合您的时间复杂度要求,我无法判断:

const inputs = [
    [{ 0: "small" }, { 0: "large" }],
    [{ 0: "small" }, { 0: "large" }, { 1: "red" }],
    [{ 0: "small" }, { 0: "large" }, { 1: "red" }, { 2: "cake" }],
    [{ 0: "small" }, { 0: "large" }, { 1: "red" }, { 1: "orange" }, { 2: "cake" }],
    [{ 0: "small" }, { 0: "large" }, { 1: "red" }, { 1: "orange" }, { 1: "blue" }, { 2: "cake" }, { 2: "ice" }],
];

function permutate(results, todo) {
    // If we have no layers left to go through, return the results
    if (!todo.length) return results;
    // Get first element of todo and store the rest for later
    const [layer, ...rest] = todo;
    // Flatmap that for example with:
    //   results = ['a', 'b']
    //   layer = [1, 2, 3]
    //  maps the results into:
    //    [ ['a.1', 'a.2', 'a.3'], ['b.1', 'b.2', 'b.3'] ]
    //  which will then be flattened together.
    results = results.flatMap(result => {
        return layer.map(value => `${result}.${value}`);
    });
    // After that, we permutate the rest of the layers
    return permutate(results, rest);
}

function getCombinations(input) {
    console.log('getCombinations for:', input);
    // Split per layer
    const layers = [];
    for (const obj of input) {
        for (const level in obj) {
            let layer = layers[level];
            if (!layer) layer = layers[level] = [];
            layer.push(obj[level]);
        }
    }
    // Now we have e.g. [ ['small', 'large'], ['red', 'orange'], ['cake', 'ice'] ]
    console.log('layers:', layers);
    // We immediately pass layer 0 as an array of results
    // then for every other layer, we build upon the (previous) results
    return permutate(layers[0], layers.slice(1));
}

for (const input of inputs) {
    console.log('========');
    const combs = getCombinations(input);
    console.log('combinations:', combs);
}

如果您的输入格式更好,那将更高效且更易于编码。

【讨论】:

    【解决方案3】:

    相当简洁的解决方案按键分组,然后在结果的前两个元素上使用修改后的 zip,直到只剩下一个元素,然后 flat() 并返回。

    function getOrderedPermutations(arr) {
      const combine = (a, b) => a.flatMap(a_ => b.map(b_ => `${a_}.${b_}`));
    
      let grouped = Object.values(arr.reduce((a, o) => (
        Object.entries(o).forEach(([k, v]) => (a[k] ??= []).push(v)), a), {})
      );
    
      let i = grouped.length - 1;
      while (i--) {
        const [a, b, ...rest] = grouped;
        grouped = [combine(a, b), ...rest];
      }
    
      return grouped.flat();
    }
    
    const inputs = [[{ 0: "small" }, { 0: "large" }], [{ 0: "small" }, { 0: "large" }, { 1: "red" }], [{ 0: "small" }, { 0: "large" }, { 1: "red" }, { 2: "cake" }], [{ 0: "small" }, { 0: "large" }, { 1: "red" }, { 1: "orange" }, { 2: "cake" }], [{ 0: "small" }, { 0: "large" }, { 1: "red" }, { 1: "orange" }, { 1: "blue" }, { 2: "cake" }, { 2: "ice" }],];
    
    // Log tests
    for (const input of inputs) {
      console.log('---');
      console.log('Input: ', input.map(o => `[${Object.entries(o)[0]}]`).join(', '));
      console.log('---');
      console.log(getOrderedPermutations(input), '\n');
    }
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-25
      • 2017-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多