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

TypeScript实现扁平对象转带去重嵌套树形结构的方案咨询

扁平数组转多层嵌套树形结构实现方案

核心思路

通过逐层分组+映射去重的方式构建树形结构:

  1. 从顶层make开始,用对象存储已存在的节点,避免重复创建
  2. 依次向下处理classification、segment、model层级,每层先检查节点是否存在,不存在则创建并加入对应列表
  3. 最终将存储节点的对象转为数组,得到标准树形结构

示例输入

const inputData = [
  {
    make: "Toyota",
    classification: "Sedan",
    segment: "Mid-size",
    model: "Camry",
    catalogDetail: { id: 1, price: 25000 }
  },
  {
    make: "Toyota",
    classification: "Sedan",
    segment: "Mid-size",
    model: "Camry",
    catalogDetail: { id: 1, price: 25000 } // 重复数据,需自动去重
  },
  {
    make: "Toyota",
    classification: "SUV",
    segment: "Compact",
    model: "RAV4",
    catalogDetail: { id: 2, price: 30000 }
  },
  {
    make: "Honda",
    classification: "Sedan",
    segment: "Compact",
    model: "Civic",
    catalogDetail: { id: 3, price: 22000 }
  }
];

期望输出

const expectedOutput = [
  {
    make: "Toyota",
    classifications: [
      {
        classification: "Sedan",
        segments: [
          {
            segment: "Mid-size",
            models: [
              {
                model: "Camry",
                catalogDetail: { id: 1, price: 25000 }
              }
            ]
          }
        ]
      },
      {
        classification: "SUV",
        segments: [
          {
            segment: "Compact",
            models: [
              {
                model: "RAV4",
                catalogDetail: { id: 2, price: 30000 }
              }
            ]
          }
        ]
      }
    ]
  },
  {
    make: "Honda",
    classifications: [
      {
        classification: "Sedan",
        segments: [
          {
            segment: "Compact",
            models: [
              {
                model: "Civic",
                catalogDetail: { id: 3, price: 22000 }
              }
            ]
          }
        ]
      }
    ]
  }
];

基础实现代码

适合中小数据量,逻辑直观:

function buildNestedTree(data) {
  const makeMap = {};

  data.forEach(item => {
    // 第一层:创建或获取make节点
    if (!makeMap[item.make]) {
      makeMap[item.make] = {
        make: item.make,
        classifications: []
      };
    }
    const currentMake = makeMap[item.make];

    // 第二层:创建或获取classification节点
    let classificationNode = currentMake.classifications.find(c => c.classification === item.classification);
    if (!classificationNode) {
      classificationNode = { classification: item.classification, segments: [] };
      currentMake.classifications.push(classificationNode);
    }

    // 第三层:创建或获取segment节点
    let segmentNode = classificationNode.segments.find(s => s.segment === item.segment);
    if (!segmentNode) {
      segmentNode = { segment: item.segment, models: [] };
      classificationNode.segments.push(segmentNode);
    }

    // 第四层:创建或获取model节点(绑定catalogDetail)
    let modelNode = segmentNode.models.find(m => m.model === item.model);
    if (!modelNode) {
      modelNode = { model: item.model, catalogDetail: item.catalogDetail };
      segmentNode.models.push(modelNode);
    }
    // 若需更新重复model的catalogDetail,可在此替换为最新值
  });

  return Object.values(makeMap);
}

// 调用示例
const result = buildNestedTree(inputData);
console.log(result);

大数据量优化版(适配6800条数据)

上述代码中find方法为O(n)查找,大数据量下性能会下降。改用对象映射实现O(1)查找,大幅提升效率:

function buildNestedTreeOptimized(data) {
  const makeMap = {};

  data.forEach(item => {
    // 第一层:make映射
    if (!makeMap[item.make]) {
      makeMap[item.make] = {
        make: item.make,
        classifications: {}, // 用对象存储已存在的classification,key为值
        classificationsList: [] // 最终输出的数组
      };
    }
    const currentMake = makeMap[item.make];

    // 第二层:classification映射
    if (!currentMake.classifications[item.classification]) {
      const classNode = {
        classification: item.classification,
        segments: {},
        segmentsList: []
      };
      currentMake.classifications[item.classification] = classNode;
      currentMake.classificationsList.push(classNode);
    }
    const currentClass = currentMake.classifications[item.classification];

    // 第三层:segment映射
    if (!currentClass.segments[item.segment]) {
      const segNode = {
        segment: item.segment,
        models: {},
        modelsList: []
      };
      currentClass.segments[item.segment] = segNode;
      currentClass.segmentsList.push(segNode);
    }
    const currentSeg = currentClass.segments[item.segment];

    // 第四层:model映射(绑定catalogDetail)
    if (!currentSeg.models[item.model]) {
      const modelNode = { model: item.model, catalogDetail: item.catalogDetail };
      currentSeg.models[item.model] = modelNode;
      currentSeg.modelsList.push(modelNode);
    }
  });

  // 转换映射对象为最终数组结构
  return Object.values(makeMap).map(makeItem => {
    delete makeItem.classifications;
    makeItem.classifications = makeItem.classificationsList;
    delete makeItem.classificationsList;

    makeItem.classifications.forEach(classItem => {
      delete classItem.segments;
      classItem.segments = classItem.segmentsList;
      delete classItem.segmentsList;

      classItem.segments.forEach(segItem => {
        delete segItem.models;
        segItem.models = segItem.modelsList;
        delete segItem.modelsList;
      });
    });

    return makeItem;
  });
}

常见错误排查

如果你的代码未生成正确结构,可能是以下原因:

  • 未做去重判断:直接向层级列表push节点,导致重复的make/classification等节点
  • 层级逻辑混乱:跳过了某一层的存在性检查,导致子节点直接挂载到错误的父节点下
  • catalogDetail绑定错误:未将catalogDetail与model关联,导致一个model对应多个重复的catalogDetail

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:01:12