【问题标题】:All Array Combination in JavaScriptJavaScript 中的所有数组组合
【发布时间】:2021-10-16 22:24:12
【问题描述】:

需要数组的所有可能组合,包括组合的反转。

例如:

var b = ['a1','b1','a','b'];

需要组合为:

a1,b1,a,b
a1b1,a1a,a1b, b1a1,b1a,b1b, ......,
a1b1a,a1b1b,a1ab1,a1bb1,........,
a1b1ab,a1b1ba.....bab1a1

所有 64 种组合(如果数组有 4 个元素)。 我使用 ArrayList 和 Collection API 在 java 中找到了解决方案,但现在我需要一个纯 JavaScript ES5 解决方案。

我尝试了以下方法,但它只提供了较少的组合。

function getCombinations(chars) {
    var result = [];
    var f = function (prefix, chars) {
        for (var i = 0; i < chars.length; i++) {
            result.push(prefix + chars[i]);
            f(prefix + chars[i], chars.slice(i + 1));
        }
    }
    f('', chars);
    return result;
}

【问题讨论】:

  • 你检查过这个了吗? stackoverflow.com/questions/4331092/… 你期望 64 个值是怎么发生的?不应该是 256 吗?
  • 我已经浏览过上面的链接,它主要处理多个数组。
  • @Bergi 但是这个当前的问题还包括不同种类的排列。
  • @Bergi 您标记的问题也不是重复的,因为它不包括组合的所有排列。 (我还有一个关于版主单方面标记他们自己回答的重复项的元警告。)
  • @vivek_23 你可能是对的 - 此处所需的结果同时包含 a1b1b1a1,还包含 a1b1babab1a1,它们是排列组合。不过,其他人似乎不见了。

标签: javascript algorithm combinatorics


【解决方案1】:

让我们把您的要求变成文字:对于每个起始元素,附加其余元素的所有组合的所有排列。

function f(A, comb=[], result=[comb]){
  return A.reduce((acc, a, i) => acc.concat(f(A.slice(0,i).concat(A.slice(i+1)), comb.concat(a))), result);
}

console.log(JSON.stringify(f(['a', 'b', 'c', 'd'])));

【讨论】:

  • 我真的不是故意的——我认为在 StackOverflow 上提问的主要目的(作为新手)是为了学习,而不仅仅是为了解决问题。因此,将解决方案减少到 3 行可能很方便,但对眼睛来说真的很重。不过,这是一个很好的解决方案。
  • @Smytt 相反 - 我的回答为 OP 和其他人提供了一个很好的学习机会。你能告诉我怎么做吗?
  • 您命名变量的方式、使用大写字母和不完整的词可能会产生误导。此外,函数调用中的函数调用 - 它只需要大量剖析才能理解它在做什么。
  • @Smytt 天哪。 A 是标记数组的最常用方法之一(几乎每个在线问题都将A[i] 列为数组选择)。 result 就是它的标签,comb 是“组合”的缩写(这真的是个问题吗?)。最后,我们有一个递归调用和一个对两个 JavaScript 数组方法的调用。你在说什么?在我看来,您对必须学习新事物感到不满。
  • 无需防御。正如我所说,我只是分享了一个观点。
【解决方案2】:

一个简单的递归将处理这个问题。看看吧:

function getCombinations(chars) {
  let combinations = [];
  chars.forEach((char, i) => {
    let word = '';
    buildWord(word + char, [i], chars, combinations)
  });
  return combinations;
}

function buildWord(word, usedIndexes, chars, combinations) {
  combinations.push(word);
  chars.forEach((char, i) => {
    if (usedIndexes.indexOf(i) === -1) {
      let newUsedIndexesArray = Array.from(usedIndexes);
      newUsedIndexesArray.push(i);
      buildWord(word + char, newUsedIndexesArray, chars, combinations)
    }
  });
}

console.log('Total: ' + getCombinations(['a1', 'b1', 'a', 'b']).length)
console.log(getCombinations(['a1', 'b1', 'a', 'b']))

【讨论】:

  • 是的。我编辑了它。我假设排列需要包括所有 4 个成员。所以这现在有效 - 无需重复成员的排列
  • 这是 JavaScript ES5 吗?
  • 刚刚编辑它以满足您的 ES5 要求。扩展运算符 (...) 和 Array.prototype.includes 都较晚出现,无法使用。如您所见,代码看起来有点重。
【解决方案3】:

下面是一种迭代方法。我们从排列长度 1 到长度(给定 chars 中的字符数),并为每个长度生成所有可能的组合。 我们维护set 以避免重复,isValidPermutation() 检查是否可以从给定的chars 集合中进行组合以避免无效组合。

function getCombinations(chars) {
  if (chars === undefined || chars === null || chars.length === 0) return [];
  var final_result = [];
  var temp_result_1 = chars.slice();
  var set = {};
  /* for initial set of elements */
  for (var i = 0; i < temp_result_1.length; ++i) {
    if (set[temp_result_1[i]] === undefined) {
      set[temp_result_1[i]] = true;
      final_result.push(temp_result_1[i]);
    }
  }

  /* go from 2 to length(since length 1 is captured above) to get all permutations of combinations */
  for (var len = 2; len <= chars.length; ++len) {
    var temp_result_2 = [];
    for (var i = 0; i < chars.length; ++i) {
      for (var j = 0; j < temp_result_1.length; ++j) {
        var current_permutation = chars[i] + "," + temp_result_1[j];
        if (set[current_permutation] === undefined && isValidPermutation(current_permutation, chars)) {
          temp_result_2.push(current_permutation);
          set[current_permutation] = true;
        }
      }
    }
    temp_result_1 = temp_result_2;
    final_result = final_result.concat(temp_result_1);
  }

  return final_result.map((each) => each.split(",").join(""));
}
/* to check if actually a combination is true and possible from current set of chars */
function isValidPermutation(current_permutation, chars) {
  var hash = {};
  current_permutation = current_permutation.split(",");
  for (var i = 0; i < chars.length; ++i) {
    if (hash[chars[i]] === undefined) hash[chars[i]] = 0;
    hash[chars[i]]++;
  }

  for (var i = 0; i < current_permutation.length; ++i) {
    hash[current_permutation[i]]--;
    if (hash[current_permutation[i]] < 0) return false;
  }

  return true;
}

var b = ['a1', 'b1', 'a', 'b'];
console.log(getCombinations(b));

由于您需要 ECMAScript 5 解决方案,因此您更改最后一行

return final_result.map((each) => each.split(",").join(""));

 for(var i=0;i<final_result.length;++i){
      final_result[i] = final_result[i].split(",").join("");
  }

  return final_result;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 2020-10-21
    • 2014-02-11
    • 2018-08-18
    相关资源
    最近更新 更多