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

Itertools.combinations in Javascript - Stack Overflow

programmeradmin0浏览0评论

Is there a similar library as Python's itertools in JavaScript? I'm interested in permutations and combinations especially.

I'm not using Node.js.

I want to do something like this:

array = ['a', 'b', 'c', 'd'];

//return non-duplicate combinations of length 2
['a', 'b']
['a', 'c']
['a', 'd']
['b', 'c']
['b', 'd']
['c', 'd']

Thanks! :)

Is there a similar library as Python's itertools in JavaScript? I'm interested in permutations and combinations especially.

I'm not using Node.js.

I want to do something like this:

array = ['a', 'b', 'c', 'd'];

//return non-duplicate combinations of length 2
['a', 'b']
['a', 'c']
['a', 'd']
['b', 'c']
['b', 'd']
['c', 'd']

Thanks! :)

Share Improve this question edited Aug 22, 2017 at 12:04 MSeifert 153k41 gold badges350 silver badges366 bronze badges asked Aug 22, 2017 at 9:11 Andrej HuckoAndrej Hucko 5301 gold badge5 silver badges15 bronze badges 6
  • You might want to have a look at Lodash – Andrei Matracaru Commented Aug 22, 2017 at 9:12
  • @AndreiMatracaru Could you be more specific ? Can you show an example ? :) Thanks! – Andrej Hucko Commented Aug 22, 2017 at 9:14
  • check this – Durga Commented Aug 22, 2017 at 9:19
  • array has unique elements or it can be like ['a','b','c','d','a'] and the result will be the same? – bluehipy Commented Aug 22, 2017 at 9:27
  • @bluehipy the accepted answer is what i wanted the rest i can workout but thanks ! :) – Andrej Hucko Commented Aug 22, 2017 at 9:35
 |  Show 1 more comment

4 Answers 4

Reset to default 8

You could use a recursive approach for gettign the permutation of the given array with a specified size.

function getPermutations(array, size) {

    function p(t, i) {
        if (t.length === size) {
            result.push(t);
            return;
        }
        if (i + 1 > array.length) {
            return;
        }
        p(t.concat(array[i]), i + 1);
        p(t, i + 1);
    }

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

var array = ['a', 'b', 'c', 'd'];

console.log(getPermutations(array, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can use my es-iter library, which is almost one to one port of Python's itertools but in JS way.

https://github.com/abozhilov/ES-Iter#combinationsr

I like itertools.combinations and wanted a memory-efficient JavaScript generator function, but couldn't quickly find an acceptable library so I rolled my own.

It's in TypeScript (to help me keep track of bookkeeping), but I'll append the transpiled JavaScript at the bottom.

function* range(start: number, end: number) {
  for (; start <= end; ++start) { yield start; }
}

function last<T>(arr: T[]) { return arr[arr.length - 1]; }

function* numericCombinations(n: number, r: number, loc: number[] = []): IterableIterator<number[]> {
  const idx = loc.length;
  if (idx === r) {
    yield loc;
    return;
  }
  for (let next of range(idx ? last(loc) + 1 : 0, n - r + idx)) { yield* numericCombinations(n, r, loc.concat(next)); }
}

function* combinations<T>(arr: T[], r: number) {
  for (let idxs of numericCombinations(arr.length, r)) { yield idxs.map(i => arr[i]); }
}

All the black magic is in the numericCombinations function, which is a recursive generator—see MDN documentation on yield*. The actual combinations function just wraps it to match the Python API.

I can put this in a .ts file and put this at the bottom of it:

if (module === require.main) {
  const shorts = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
  let i = 0;
  for (let o of combinations(shorts, 7)) { i++; }
  console.log(i);
}

and Node prints out 133784560 in less than 2.5 minutes, with minimal memory usage, on my 2015-vintage laptop. That is, it generated all hundred thirty-four million ways you can choose seven cards from a standard deck of fifty-two playing cards (i.e., all complete Texas hold ’em hands) without burdening memory or overly-nesting recursive function calls.

(Python3 can do this in 20 seconds, or 7× faster… speedups to the above welcome.)


JavaScript code:

function* range(start, end) {
  for (; start <= end; ++start) { yield start; }
}
function last(arr) { return arr[arr.length - 1]; }
function* numericCombinations(n, r, loc = []) {
  const idx = loc.length;
  if (idx === r) {
    yield loc;
    return;
  }
  for (let next of range(idx ? last(loc) + 1 : 0, n - r + idx)) { yield* numericCombinations(n, r, loc.concat(next)); }
}
function* combinations(arr, r) {
  for (let idxs of numericCombinations(arr.length, r)) { yield idxs.map(i => arr[i]); }
}

For cartesian products, you might want to check this verbose example that leverages lodash. The functionality is similar to itertools.product in Python.

发布评论

评论列表(0)

  1. 暂无评论