JavaScript中多层级父子对象的扁平化排序及层级标记实现
多级父子数组转扁平层级结构解决方案
问题描述
需要将包含多级父子关系的对象数组,转换为子项紧邻父项的扁平结构,同时为每个元素添加level字段标识其层级(根节点层级为1,子节点层级依次递增)。
解决方案(JavaScript实现)
以下代码支持任意层级的父子关系转换,步骤清晰且易扩展:
1. 定义原数组
const originalArray = [ { "id": 1, "name": "Parent" }, { "id": 2, "name": "Child 1", "parent_id": 1 }, { "id": 3, "name": "Grand Child 1", "parent_id": 2 }, { "id": 4, "name": "Grand Child 2", "parent_id": 2 }, { "id": 5, "name": "Child 2", "parent_id": 1 }, { "id": 7, "name": "Grand Child 3", "parent_id": 2 }, ];
2. 转换函数实现
function flattenHierarchy(arr) { // 构建ID到对象的映射,为每个对象初始化children数组 const idMap = {}; arr.forEach(item => { idMap[item.id] = { ...item, children: [] }; }); // 构建树状结构:将子节点挂载到对应父节点的children中 const rootNodes = []; arr.forEach(item => { if (item.parent_id) { idMap[item.parent_id].children.push(idMap[item.id]); } else { rootNodes.push(idMap[item.id]); } }); // 递归遍历树,生成带level的扁平数组 const result = []; const traverse = (node, currentLevel) => { // 移除children字段,添加level后推入结果 const { children, ...nodeWithoutChildren } = node; result.push({ ...nodeWithoutChildren, level: currentLevel }); // 递归处理子节点,层级+1 node.children.forEach(child => traverse(child, currentLevel + 1)); }; // 遍历所有根节点(无parent_id的节点),初始层级为1 rootNodes.forEach(root => traverse(root, 1)); return result; }
3. 调用并输出结果
const flattenedResult = flattenHierarchy(originalArray); console.log(JSON.stringify(flattenedResult, null, 2));
输出结果
[ { "id": 1, "name": "Parent", "level": 1 }, { "id": 2, "name": "Child 1", "parent_id": 1, "level": 2 }, { "id": 3, "name": "Grand Child 1", "parent_id": 2, "level": 3 }, { "id": 4, "name": "Grand Child 2", "parent_id": 2, "level": 3 }, { "id": 7, "name": "Grand Child 3", "parent_id": 2, "level": 3 }, { "id": 5, "name": "Child 2", "parent_id": 1, "level": 2 }, ]
核心逻辑说明
- 映射表构建:通过ID快速定位对象,避免多次遍历数组查找父项,提升性能。
- 树结构构建:将分散的父子关系整理为树状,便于层级遍历。
- 递归遍历:深度优先遍历树结构,确保子项紧跟父项,同时自动计算层级。
内容的提问来源于stack exchange,提问作者Hassan
相关产品推荐
相关产品推荐

