如何在JavaScript中高效将扁平数组转为带children的树形结构?
JavaScript 高效实现扁平数组转层级化children数组
需求说明
将扁平对象数组按type、lastname层级分组,父节点的age为子节点age总和,生成带children属性的层级数组。
源数据格式
const arrayObjects = [ { name: "Alice", lastname: "Silva", age: 25, type: "A", city: "São Paulo" }, { name: "Bruno", lastname: "Pereira", age: 30, type: "A", city: "Belo Horizonte" }, { name: "Camila", lastname: "Silva", age: 35, type: "B", city: "São Paulo" }, { name: "Daniel", lastname: "Pereira", age: 40, type: "B", city: "Belo Horizonte" }, { name: "Eduardo", lastname: "Silva", age: 45, type: "B", city: "Belo Horizonte" }, { name: "Fernanda", lastname: "Silva", age: 50, type: "A", city: "São Paulo" }, ];
期望输出格式
const arrayOutPut = [ { age: 105, type: "A", children: [ { age: 75, type: "A", lastname: "Silva", children: [ { name: "Alice", lastname: "Silva", age: 25, type: "A", city: "São Paulo" }, { name: "Fernanda", lastname: "Silva", age: 50, type: "A", city: "São Paulo" } ] }, { age: 30, type: "A", lastname: "Pereira", children: [ { name: "Bruno", lastname: "Pereira", age: 30, type: "A", city: "Belo Horizonte" } ] } ] } ]
高效实现方案
核心思路是用reduce完成分层分组,再基于分组结果构建层级结构并计算age总和,全程仅需遍历源数组一次,性能高效。
function transformFlatArray(arr) { // 按 type -> lastname 两层分组 const grouped = arr.reduce((acc, item) => { if (!acc[item.type]) acc[item.type] = {}; if (!acc[item.type][item.lastname]) acc[item.type][item.lastname] = []; acc[item.type][item.lastname].push(item); return acc; }, {}); // 构建最终层级数组 return Object.entries(grouped) // 若需过滤特定type,添加此行:.filter(([type]) => type === "A") .map(([type, lastnameGroups]) => { const children = Object.entries(lastnameGroups).map(([lastname, items]) => ({ age: items.reduce((sum, item) => sum + item.age, 0), type, lastname, children: [...items] })); return { age: children.reduce((sum, child) => sum + child.age, 0), type, children }; }); } // 调用示例 const result = transformFlatArray(arrayObjects); console.log(result);
代码说明
- 分组阶段:通过一次
reduce遍历,将元素按type和lastname嵌套分组,把同类型同姓氏的元素归入同一集合。 - 层级构建:
- 遍历每个
type分组,为每个lastname组生成子节点,子节点的age是组内元素的年龄总和,children为组内原始元素。 - 计算每个
type节点的总年龄(所有子节点年龄之和),生成顶层节点。
- 遍历每个
- 性能优势:时间复杂度为O(n)(n为源数组长度),仅需一次遍历源数组,后续操作均为线性处理,是高效的实现方式。
内容的提问来源于stack exchange,提问作者Diogo
相关产品推荐
相关产品推荐

