最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - combinations of size N from an array - Stack Overflow

programmeradmin0浏览0评论

I am trying to build a javascript function to get all binations of size N from an array. lets say I got:

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

binationsOfN(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"],
…. ]

I am trying to build a javascript function to get all binations of size N from an array. lets say I got:

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

binationsOfN(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"],
…. ]
Share Improve this question edited May 6, 2016 at 14:52 guest271314 1 asked May 6, 2016 at 14:38 Rodrigo ZurekRodrigo Zurek 4,5759 gold badges35 silver badges45 bronze badges 2
  • 2 So, what have tried so far? – nils Commented May 6, 2016 at 14:42
  • Is requirement to only iterate first four n items within Xarray ? – guest271314 Commented May 6, 2016 at 14:53
Add a ment  | 

3 Answers 3

Reset to default 5

Doing this by yourself might be rather tough, because I've tried that. There's already a js tool that does this for you, binations.js

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

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

Well i have to say i hate JS sometimes. I definitely hate push() that for sure. When you do functional you need more and more a reference to the mutated objects. A method mutating an object it's called upon shall return a reference to that object.

Anyways the code could have been much simpler looking but alas... this is as far as it gets. It's nothing more than a simple recursive run. The plicated looking parts are actually the stupid parts such as;

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

in fact means delete the element at index position i and return the resulting array. When you need to use this functionality as a single instruction or a chainable instruction as an argument to a function this seems to be the only way. Just like the

(t.push(c),t)

instruction. Which means push c to t array and return t array. Silly push(c) would return the length... I hate it. You give me the reference man i can get the length from that if needed. So the rest is easy to understand.

So i have two solutions one for the permutations and one for the binations.

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

And now the binations...

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

I offer two solutions, the first with a result which includes the items at any place.

function bine(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(bine(["19", "21", "42", "23", "25", "28"], 4), 0, 4) + '</pre>');

The second which returns only one item at in original order. This result set is shorter then the above and like the answer of akinuri.

function bine(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(bine(["19", "21", "42", "23", "25", "28"], 4), 0, 4) + '</pre>');

发布评论

评论列表(0)

  1. 暂无评论