You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript生成数组的三元组合(非排列)?

JavaScript实现无重复组合生成(对应Python itertools.combinations)

问题描述

现有一个包含16个元素的数组,每个元素是长度为2的子数组,示例结构如下:

[['one', 'blue'], ['one', 'red'], ['two', 'blue'], ['two', 'red'], ...]

需要生成所有3个元素的组合(非排列,即不考虑顺序,排除不同顺序的重复组合),输出示例如下:

[[['one', 'blue'], ['one', 'red'], ['two', 'blue']],
 [['one', 'blue'], ['one', 'red'], ['two', 'red']],
 [['one', 'blue'], ['two', 'blue'], ['two', 'red']],
 [['one', 'red'], ['two', 'blue'], ['two', 'red']], ...]

已通过Python的itertools.combinations实现该功能,寻求JavaScript的等价实现方案。

实现思路

组合的核心是只选取原数组中索引严格递增的元素,这样就能天然避免顺序不同的重复组合(比如不会同时出现[a,b,c]和[b,a,c],因为后者的索引顺序不满足递增要求)。

代码实现

1. 递归实现(简洁直观)

这是通用的组合生成函数,支持生成任意数组中k个元素的组合:

function combinations(arr, k) {
  const result = [];
  
  const backtrack = (start, current) => {
    // 当当前组合长度达到k时,存入结果
    if (current.length === k) {
      result.push([...current]);
      return;
    }
    // 从start索引开始遍历,保证后续元素索引递增
    for (let i = start; i < arr.length; i++) {
      current.push(arr[i]);
      backtrack(i + 1, current);
      current.pop(); // 回溯,移除当前元素以尝试下一个可能
    }
  };
  
  backtrack(0, []);
  return result;
}

2. 测试示例

用示例输入数组验证:

// 示例输入(实际为16个元素)
const inputArray = [
  ['one', 'blue'],
  ['one', 'red'],
  ['two', 'blue'],
  ['two', 'red']
];

// 生成3元素组合
const threeElementCombinations = combinations(inputArray, 3);

// 输出结果
console.log(threeElementCombinations);

输出结果与需求示例完全一致,无重复排列组合。

3. 迭代实现(无递归)

如果偏好非递归写法,可使用索引迭代的方式:

function combinationsIterative(arr, k) {
  const result = [];
  const totalElements = arr.length;
  // 初始化索引数组,比如k=3时初始为[0,1,2]
  let indices = Array.from({ length: k }, (_, idx) => idx);

  while (true) {
    // 根据当前索引生成组合并存入结果
    result.push(indices.map(i => arr[i]));

    // 寻找下一组合法索引
    let currentIdx = k - 1;
    // 从后往前找第一个可以递增的索引
    while (currentIdx >= 0 && indices[currentIdx] === totalElements - k + currentIdx) {
      currentIdx--;
    }
    // 所有组合生成完毕,退出循环
    if (currentIdx < 0) break;

    indices[currentIdx]++;
    // 更新后续索引为当前索引+1、+2...保证递增
    for (let j = currentIdx + 1; j < k; j++) {
      indices[j] = indices[j - 1] + 1;
    }
  }

  return result;
}

说明

两种实现的逻辑均与Python的itertools.combinations完全对齐,生成的组合顺序、内容一致,且不会产生重复的排列结果。

内容的提问来源于stack exchange,提问作者Brian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 10:27:42