【问题标题】:Itertools.combinations in JavascriptJavascript 中的 Itertools.combinations
【发布时间】:2021-03-01 07:44:53
【问题描述】:

在 JavaScript 中是否有与 Python 的 itertools 类似的库?我对排列组合特别感兴趣。

我没有使用 Node.js。

我想做这样的事情:

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

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

谢谢! :)

【问题讨论】:

  • 你可能想看看Lodash
  • @AndreiMatracaru 你能说得更具体一点吗?你能举个例子吗? :) 谢谢!
  • 检查this
  • array 有独特的元素,或者它可以像['a','b','c','d','a'] 一样,结果会一样吗?
  • @bluehipy 接受的答案是我想要的,其余的我可以锻炼,但谢谢! :)

标签: javascript


【解决方案1】:

您可以使用递归方法来获取具有指定大小的给定数组的排列。

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; }

【讨论】:

【解决方案2】:

您可以使用我的 es-iter 库,它几乎是 Python 的 itertools 的一对一端口,但以 JS 方式。

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

【讨论】:

    【解决方案3】:

    我喜欢 itertools.combinations 并想要一个内存效率高的 JavaScript generator function,但无法快速找到可接受的库,所以我自己开发了。

    它在 TypeScript 中(帮助我跟踪簿记),但我会在底部附加转译后的 JavaScript。

    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]); }
    }
    

    所有的黑魔法都在 numericCombinations 函数中,它是一个递归生成器——请参阅 yield* 上的 MDN 文档。实际的 combinations 函数只是将其包装以匹配 Python API。

    我可以把它放在一个.ts 文件中并把它放在它的底部:

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

    Node 在不到 2.5 分钟的时间内打印出 133784560,并且在我的 2015 年老式笔记本电脑上使用最少的内存。也就是说,它生成了所有亿三千四百万种方式,您可以从一副标准的五十二张扑克牌中选择七张牌(即所有完整的德州扑克牌),而不会增加记忆力或过度使用- 嵌套递归函数调用。

    (Python3 可以在 20 秒内完成此操作,或者快 7 倍……加速到上述欢迎。)


    JavaScript 代码:

    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]); }
    }
    

    【讨论】:

      【解决方案4】:

      对于笛卡尔积,您可能需要查看利用lodashthis 详细示例。功能类似于 Python 中的itertools.product

      【讨论】:

      • 由于安全原因无法访问该页面。你能把它展示在别的地方吗?谢谢 ! :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-06
      • 1970-01-01
      • 1970-01-01
      • 2019-07-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多