如何用JavaScript将对象数组转换为深度树形数组?
如何高效将扁平对象数组转换为多层嵌套结构?
需求描述
需要将扁平的对象数组转换为支持任意层级(部门、分类、子分类)的深度嵌套结构。
输入示例
[ { divName: "ABC", divId: 123, catName: "XYZ", catId: 456, subCatName: "PQR", subCatId: 781 }, { divName: "ABC", divId: 123, catName: "YQP", catId: 281, subCatName: "FYI", subCatId: 231 }, { divName: "ABC", divId: 123, catName: "XYZ", catId: 456, subCatName: "YAB", subCatId: 587 } ]
预期输出
[ { divName: "ABC", divId: 123, categories: [ { catName: "XYZ", catId: 456, subCategories: [ { subCatName: "PQR", subCatId: 781 }, { subCatName: "YAB", subCatId: 587 } ] }, { catName: "YQP", catId: 281, subCategories: [ { subCatName: "FYI", subCatId: 231 } ] } ] } ]
现有实现代码
nonCompetitorData.map((data, idx) => { if(idx === 0) { downloadData.push({"divisionName": data.divisionName, "divisionId": data.divisionId}); } else { if (!downloadData[0].categories) { downloadData[0].categories = []; downloadData[0].categories.push({ "categoryName": data.categoryName, "categoryId": data.categoryId }) } else { if(downloadData[0].categories) { if(!downloadData[0].categories.some(c => c.categoryName === data.categoryName)) { downloadData[0].categories.push({ "categoryName": data.categoryName, "categoryId": data.categoryId }) } } downloadData[0].categories.forEach((cat, i) => { if(!cat.subCategories) { console.log("Categories",downloadData[0].categories[i]); downloadData[0].categories[i].subCategories = []; downloadData[0].categories[i].subCategories.push({ "subCategoryName": data.subCategoryName, "subCategoryId": data.subCategoryId }); } else { if(cat.subCategories) { if(!cat.subCategories.some(c => c.subCategoryName === data.subCategoryName)) { downloadData[0].categories[i].subCategories.push({ "subCategoryName": data.subCategoryName, "subCategoryId": data.subCategoryId }) } } } }); } } });
优化实现方案
可以利用Array.prototype.reduce实现更简洁、高效且可扩展的转换逻辑,核心是通过唯一标识(如divId、catId)快速定位已存在的层级节点,避免重复遍历数组:
function transformFlatData(flatData) { return flatData.reduce((result, item) => { // 1. 查找或创建部门节点 let division = result.find(div => div.divId === item.divId); if (!division) { division = { divName: item.divName, divId: item.divId, categories: [] }; result.push(division); } // 2. 查找或创建分类节点 let category = division.categories.find(cat => cat.catId === item.catId); if (!category) { category = { catName: item.catName, catId: item.catId, subCategories: [] }; division.categories.push(category); } // 3. 查找或创建子分类节点(避免重复添加) const existingSubCat = category.subCategories.find(sub => sub.subCatId === item.subCatId); if (!existingSubCat) { category.subCategories.push({ subCatName: item.subCatName, subCatId: item.subCatId }); } return result; }, []); } // 使用示例 const transformedData = transformFlatData(yourFlatDataArray);
优化点说明
- 逻辑清晰:每一层级处理逻辑独立拆分,可读性更强,便于后续修改维护
- 效率提升:用
find替代多次forEach+some的组合,减少不必要的数组遍历 - 扩展性强:若后续需增加更多层级(如三级分类),只需在
reduce中添加对应查找/创建逻辑 - 通用性高:支持同时处理多个部门,解决了原代码仅能处理单个部门的局限
内容的提问来源于stack exchange,提问作者vjeta
相关产品推荐
相关产品推荐

