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

如何在JavaScript中从扁平数据生成递归嵌套数组结构

将扁平数组转换为深度嵌套树形结构

需求描述

需要将列数不固定但最后一项始终为数值的扁平数组,转换为嵌套的树形结构:遍历每行数组,按层级创建分组节点,非叶子节点包含name和children数组,叶子节点包含name和value(数值类型)。

输入示例

const inputData = [
  ["World", "Asia", "Singapore", "Asia-Singapore", "1300"],
  ["World", "Asia", "India", "Asia-India", "850"],
  ["World", "Asia-Singapore", "Bond", "Bond-Singapore", "650"],
  ["World", "Asia-Singapore", "Bond", "Singapore-Bond", "650"],
  ["World", "Asia-China", "Bond", "Bond-China", "600"],
  ["World", "Asia-China", "Bond", "China-Bond", "600"],
  ["World", "Asia-India", "Equity", "Equity-India", "500"],
  ["World", "Asia-India", "Equity", "India-Equity", "500"],
  [
    "World",
    "Asia-China",
    "Private Equity",
    "China-Private Equity",
    "400",
  ],
  [
    "World",
    "Asia-China",
    "Private Equity",
    "Private Equity -China",
    "400",
  ],
  ["World", "Asia-India", "Bond", "Bond-India", "350"],
  ["World", "Asia-India", "Bond", "India-Bond", "350"],
  [
    "Jupiter",
    "Asia-Singapore",
    "Private Equity",
    "Private Equity -Singapore",
    "350",
  ],
  [
    "Jupiter",
    "Asia-Singapore",
    "Private Equity",
    "Singapore-Private Equity",
    "350",
  ],
  ["Jupiter", "Asia-Singapore", "Equity", "Equity-Singapore", "300"],
  ["Jupiter", "Asia-Singapore", "Equity", "Singapore-Equity", "300"],
  ["Jupiter", "Asia", "China", "Asia-China", "Franky", "290"],
  ["World", "Asia-China", "Equity", "China-Equity", "250"],
  ["World", "Asia-China", "Equity", "Equity-China", "250"],
  ["World", "Asia", "China", "Asia-China", "Billy", "110"],
  ["World", "Asia", "China", "Asia-China", "Freddy", "50"],
];

期望输出结构示例

const testData = [
  {
    name: "World",
    children: [
      {
        name: "Asia",
        children: [
          {
            name: "Asia-China",
            value: 110,
          },
        ],
      },
    ],
  },
  {
    name: "Jupiter",
    children: [
      {
        name: "Asia-Singapore",
        children: [
          {
            name: "Google",
            value: 200,
          },
        ],
      },
    ],
  },
];

实现方案

基于层级遍历的思路,实现buildTree函数完成转换:

function buildTree(data) {
  const result = [];

  data.forEach((row) => {
    let currentLevel = result;
    row.slice(0, -1).forEach((name, index) => {
      let existing = currentLevel.find((item) => item.name === name);
      if (!existing) {
        // 判断当前节点是否为叶子节点(即倒数第二个元素)
        if (name === row[row.length - 2]) {
          existing = {
            name,
            value: parseInt(row[row.length - 1]),
          };
        } else {
          existing = {
            name,
            children: [],
          };
        }
        currentLevel.push(existing);
      }

      // 如果当前节点有子节点,切换到子节点层级继续处理
      if (existing.children) {
        currentLevel = existing.children;
      }
    });
  });
  return result;
}

代码说明

  • 初始化结果数组作为根节点层级
  • 遍历每一行数据,维护当前处理的层级节点数组
  • 对每行除最后一项外的元素逐个处理:
    • 检查当前层级是否已存在同名节点,不存在则创建(判断是否为叶子节点,决定带children还是value)
    • 若当前节点有子节点,切换到子节点层级继续后续元素的处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 02:49:58