TypeScript实现扁平对象转带去重嵌套树形结构的方案咨询
扁平数组转多层嵌套树形结构实现方案
核心思路
通过逐层分组+映射去重的方式构建树形结构:
- 从顶层
make开始,用对象存储已存在的节点,避免重复创建 - 依次向下处理
classification、segment、model层级,每层先检查节点是否存在,不存在则创建并加入对应列表 - 最终将存储节点的对象转为数组,得到标准树形结构
示例输入
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
相关产品推荐
相关产品推荐

