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

如何实现含一维数组的输入数组的全路径组合展开?

问题描述

我需要实现一个功能:将包含单个元素或一维数组的输入数组展开,生成所有到叶子“节点”的路径组合,暂时不清楚这个操作的特定名称。以下是规则和示例:

功能规则与示例

输入数组的元素只能是单个值或一维数组,展开规则为:每次遇到数组时,将现有所有路径拆分为与该数组元素数量一致的路径,每个拆分后的路径分别追加该数组的一个元素。

示例:

let input = [1, 2, [3, 4], [5, 6]];

处理过程:

  1. 先处理单个元素,当前结果为 [[1, 2]]
  2. 处理数组 [3,4]:将现有路径拆分,分别追加3和4,得到 [[1,2,3], [1,2,4]]
  3. 处理数组 [5,6]:将每个现有路径拆分,分别追加5和6,最终结果:
[[1, 2, 3, 5], [1, 2, 4, 5], [1, 2, 3, 6], [1, 2, 4, 6]]

遇到的问题

我尝试从后往前构建结果(用pop方法),但代码无法正常运行,也处理不了以下特殊情况:

  • input1 = [1, 2, 3](无嵌套数组,预期输出[[1,2,3]])
  • input2 = [](空输入,预期输出[[]])

我的代码如下:

function flatPath(input, result = [[]]) {
    while (input.length) {
        const last = input.pop();

        if (Array.isArray(last)) {
            result = flatPath(last, [...result, ...result]);
        } else {
            for (let ar of result) {
                result.push(last);
            }
        }
    }
    return result;
}

let result = flatPath([1, 2, [3, 4], [2, 5, 6] ]);
console.log(result);

用TypeScript编译时还会报错:

Parameter 'input' implicitly has an 'any' type.
Argument of type 'any' is not assignable to parameter of type 'never'.

请问我的代码有什么问题?有没有更规范的实现方式?


问题分析与解决

原代码的问题

  1. 逻辑错误:
    • 处理单个元素时,直接往result数组里push(last),但result是路径数组的集合,正确操作应该是给每个路径数组追加元素,而非往集合里加单个值,这会导致路径结构完全混乱。
    • 处理嵌套数组时,仅把result复制两份传入递归,这只适配数组长度为2的场景,遇到长度为3及以上的数组(比如[2,5,6])时,无法生成对应数量的路径。
    • 使用pop()会直接修改原输入数组,产生不必要的副作用,也会导致原数组被清空。
  2. TypeScript类型问题:
    • 未给input和result指定明确类型,导致TS无法推断类型,出现隐式any错误;递归调用时类型不匹配,触发never类型报错。

正确的实现方式

JavaScript版本

采用从前往后遍历的方式,逐个处理输入元素,避免修改原数组:

  • 初始结果设为[[]](空路径)
  • 遍历每个元素:
    • 若为单个值,给所有现有路径追加该值
    • 若为数组,将每个现有路径复制多份,每份分别追加数组中的一个元素
function flatPath(input) {
    let result = [[]];
    for (const item of input) {
        if (Array.isArray(item)) {
            const temp = [];
            for (const path of result) {
                for (const val of item) {
                    temp.push([...path, val]);
                }
            }
            result = temp;
        } else {
            result = result.map(path => [...path, item]);
        }
    }
    return result;
}

// 测试用例
console.log(flatPath([1, 2, [3, 4], [5, 6]]));
// 输出: [[1,2,3,5],[1,2,4,5],[1,2,3,6],[1,2,4,6]]
console.log(flatPath([1,2,3])); // 输出: [[1,2,3]]
console.log(flatPath([])); // 输出: [[]]

TypeScript版本

给函数指定泛型类型,明确输入输出的类型结构,通过TS类型检查:

function flatPath<T>(input: (T | T[])[]): T[][] {
    let result: T[][] = [[]];
    for (const item of input) {
        if (Array.isArray(item)) {
            const temp: T[][] = [];
            for (const path of result) {
                for (const val of item) {
                    temp.push([...path, val]);
                }
            }
            result = temp;
        } else {
            result = result.map(path => [...path, item]);
        }
    }
    return result;
}

// 测试用例
console.log(flatPath([1, 2, [3, 4], [5, 6]]));
console.log(flatPath([1,2,3]));
console.log(flatPath([]));

额外说明

这个操作本质是笛卡尔积的变体:每个数组元素相当于一个集合,单个元素相当于仅含一个元素的集合,最终的路径就是这些集合的笛卡尔积。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 16:24:52