【问题标题】:combinations of size N from an array数组中大小 N 的组合
【发布时间】:2018-07-25 17:04:03
【问题描述】:

我正在尝试构建一个 javascript 函数来从数组中获取大小为 N 的所有组合。 假设我得到了:

const Xarray = ["19", "21","42","23",  "25", "28"];
const n = 4;

combinationsOfN(Xarray, n) =>

[ ["19", "21", "42", "23"],
  ["19", "21", "42", "25"],
  ["19", "21", "42", "28"],
  ["19", "21", "23", "25"],
  ["19", "21", "23", "28"],
  ["19", "21", "25", "28"],
…. ]

【问题讨论】:

  • 那么,到目前为止有什么尝试?
  • 是否要求只迭代Xarray 中的前四个n 项目?

标签: javascript arrays


【解决方案1】:

自己做这件事可能相当困难,因为我已经尝试过了。已经有一个 js 工具可以为你做到这一点,combinations.js

/**
 * Copyright 2012 Akseli Palén.
 * Created 2012-07-15.
 * Licensed under the MIT license.
 */
function k_combinations(set, k) {
    var i, j, combs, head, tailcombs;
    if (k > set.length || k <= 0) {
        return [];
    }
    if (k == set.length) {
        return [set];
    }
    if (k == 1) {
        combs = [];
        for (i = 0; i < set.length; i++) {
            combs.push([set[i]]);
        }
        return combs;
    }
    combs = [];
    for (i = 0; i < set.length - k + 1; i++) {
        head = set.slice(i, i+1);
        tailcombs = k_combinations(set.slice(i + 1), k - 1);
        for (j = 0; j < tailcombs.length; j++) {
            combs.push(head.concat(tailcombs[j]));
        }
    }
    return combs;
}
function combinations(set) {
    var k, i, combs, k_combs;
    combs = [];
    for (k = 1; k <= set.length; k++) {
        k_combs = k_combinations(set, k);
        for (i = 0; i < k_combs.length; i++) {
            combs.push(k_combs[i]);
        }
    }
    return combs;
}
	
var array = ["19", "21","42","23", "25", "28"];

document.body.innerHTML += "<pre>" + JSON.stringify(k_combinations(array, 4), false, "\t") + "</pre>";

【讨论】:

    【解决方案2】:

    我不得不说我有时讨厌 JS。我肯定讨厌push()。当您执行功能时,您需要越来越多的对变异对象的引用。改变它所调用的对象的方法应返回对该对象的引用。

    无论如何,代码本来可以看起来更简单,但是唉......这是它所能得到的。这只不过是一个简单的递归运行。看起来复杂的部分实际上是愚蠢的部分,例如;

    a.slice(0,i).concat(a.slice(i+1))
    

    实际上意味着删除索引位置 i 处的元素并返回结果数组。当您需要将此功能用作单个指令或可链接指令作为函数的参数时,这似乎是唯一的方法。就像

    (t.push(c),t)
    

    说明。这意味着将 c 推送到 t 数组并返回 t 数组。愚蠢的 push(c) 会返回长度......我讨厌它。你给我参考人,如果需要,我可以从中得到长度。所以剩下的就很容易理解了。

    所以我有两种解决方案,一种用于排列,一种用于组合。

    var xarray = ["19", "21", "42", "23", "25", "28"],
             n = 4;
    
    function getPermutations(a,n,s=[],t=[]){
      return a.reduce((p,c,i,a) => { n > 1 ? getPermutations(a.slice(0,i).concat(a.slice(i+1)), n-1, p, (t.push(c),t))
                                           : p.push((t.push(c),t).slice(0));
                                     t.pop();
                                     return p},s)
    }
    document.write("<pre>" + JSON.stringify(getPermutations(xarray,n),null,2) + "</pre>");

    现在组合...

    var xarray = ["19", "21", "42", "23", "25", "28"],
             n = 4;
    
    function getCombinations(a,n,s=[],t=[]){
      return a.reduce((p,c,i,a) => { n > 1 ? getCombinations(a.slice(i+1), n-1, p, (t.push(c),t))
                                           : p.push((t.push(c),t).slice(0));
                                     t.pop();
                                     return p},s)
    }
    
    document.write("<pre>" + JSON.stringify(getCombinations(xarray,n),null,2) + "</pre>");

    【讨论】:

    • 有趣..然后找到一个边缘。
    【解决方案3】:

    我提供了两种解决方案,第一种解决方案的结果包括任何地方的项目。

    function combine(array, length) {
        function c(l, r) {
            var i, ll;
            if (r.length === length) {
                result.push(r);
                return;
            }
            for (i = 0; i < l.length; i++) {
                ll = l.slice();
                c(ll, r.concat(ll.splice(i, 1)));
            }
        }
        var result = [];
        c(array, []);
        return result;
    }
    
    document.write('<pre>' + JSON.stringify(combine(["19", "21", "42", "23", "25", "28"], 4), 0, 4) + '</pre>');

    第二个以原始顺序仅返回一项。这个结果集比上面的更短,就像akinuri的答案一样。

    function combine(array, length) {
        function c(l, r) {
            var ll = l.slice();
            if (r.length === length) {
                result.push(r);
                return;
            }
            while (ll.length) {
                c(ll, r.concat(ll.shift()));
            }
        }
        var result = [];
        c(array, []);
        return result;
    }
    
    document.write('<pre>' + JSON.stringify(combine(["19", "21", "42", "23", "25", "28"], 4), 0, 4) + '</pre>');

    【讨论】:

    • 您可能需要检查您的组合解决方案(最后一个)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 2019-05-27
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    相关资源
    最近更新 更多