js 实现扁平数组转为树形结构数组及树形结构数组转为扁平数组
// pid 代表属于的父级 id // id 代表的是自己本身的id,本身的 id 是多少 let flatArr = [ { id: 1, name: "部门1", pid: 0 }, { id: 2, name: "部门2", pid: 1 }, { id: 3, name: "部门3", pid: 1 }, { id: 4, name: "部门4", pid: 3 }, { id: 5, name: "部门5", pid: 4 }, ]; // 预期输出 // [ // { // id: 1, // name: "部门1", // pid: 0, // children: [ // { id: 2, name: "部门2", pid: 1 }, // { // id: 3, // name: "部门3", // pid: 1, // children: [ // { // id: 4, // name: "部门4", // pid: 3, // children: [{ id: 5, name: "部门5", pid: 4 }], // }, // ], // }, // ], // }, // ] // 预期输出: // 1. 子节点的pid是父节点的id,即某个对象的 pid 与 某个对象的 id 相同,则前者为后者的子节点 // 2. 返回为带有层级的对象数组 // 步骤 // 为了避免使用递归导致的性能较差,每次遍历一遍数字,这里使用 map 存储对象 // 1.先将每个对象变为通过 id 保存的具体对象的map 对象 // 2.创建结果数组 // 3.遍历传入的数组,根据传入的 parent_id(pid),获取所有父节点的对象,push 到数组中,作为第一层对象 // 4.在遍历数组过程中,获取数组的 pid,从刚才保存的对象中寻找父级对象是否存在如果存在,增加 children 属性,数组,并 push 当前对象 // arr 为传入的待转换的扁平数组 // parentId 为根节点 id function arrayToTree(arr, parentId) { // 将所有对象存到 map 中 const map = arr.reduce((prev, cur) => { // 注意:这里是浅拷贝,会修改原数组,当后续再使用原数组会出问题 prev[cur.id] = cur; return prev; }, {}); // 定义返回结果数组 let result = []; // 遍历传入的对象 for (let i = 0; i < arr.length; i++) { const item = arr[i]; // 当遍历到的对象的 pid 等于 传入的根节点的 id,说明为根节点,直接 push 到数组中 if (item.pid === parentId) { result.push(item); // 退出本次循环 continue; } // 如果不是根节点,从 map 中找到 pid 对应的对象,该对象即为当前遍历到的对象的父节点 const parent = map[item.pid]; if (parent) { // 给父节点添加 children 属性,并定义为数组 parent.children = parent.children || []; // 在数组中 push 当前子节点 parent.children.push(item); } } return result; } console.log(arrayToTree(flatArr, 0)); // 不改变原数组的方法 function arrayToTree2(items) { const result = []; // 存放结果集 const itemMap = {}; // for (const item of items) { const id = item.id; const pid = item.pid; if (!itemMap[id]) { itemMap[id] = { children: [], }; } itemMap[id] = { ...item, children: itemMap[id]["children"], }; const treeItem = itemMap[id]; if (pid === 0) { result.push(treeItem); } else { if (!itemMap[pid]) { itemMap[pid] = { children: [], }; } itemMap[pid].children.push(treeItem); } } return result; } console.log(arrayToTree2(flatArr)); let treeArr = [ { id: 1, name: "部门1", pid: 0, children: [ { id: 2, name: "部门2", pid: 1 }, { id: 3, name: "部门3", pid: 1, children: [ { id: 4, name: "部门4", pid: 3, children: [{ id: 5, name: "部门5", pid: 4 }], }, ], }, ], }, ]; // 树形结构转为扁平数组 function flatten(arr) { return arr.reduce((prev, cur) => { const { children = [], ...others } = cur; return prev.concat([{ ...others }], flatten(children)); }, []); } console.log("树形数组转为扁平数组"); console.log(flatten(treeArr)); console.log(treeArr);
// 无 pid,需要手动加 pid let treeArr1 = [ { id: 1, name: "部门1", children: [ { id: 2, name: "部门2" }, { id: 3, name: "部门3", children: [ { id: 4, name: "部门4", children: [{ id: 5, name: "部门5" }], }, ], }, ], }, ]; function treeToFlat1(treeArr, pid) { return treeArr.reduce((prev, cur) => { const { children = [], ...others } = cur; return prev.concat({ pid, ...others }, treeToFlat1(children, cur.id)); }, []); }
注意:
1. 扁平数组转为树形结构数组,如果使用递归实现,时间复杂度为 O(2^n)
2. 注意修改原数组是否有影响,如果有影响,并且有原数组引用会产生问题。
转载请注明出处:https://www.cnblogs.com/beileixinqing/p/16666662.html
参考链接: