现有两种来自同一数据源的结构
树状结构
source = [
{
id: 1,
name: "X公司",
pid: 0, // 父级id
children: [
{
id: 2,
name: "技术部",
pid: 1,
children: [],
},
{
id: 3,
name: "人力资源部",
pid: 1,
children: [
{
id: 4,
pid: 3,
name: "招聘组",
},
],
},
],
},
];
扁平结构
source = [
{id: 1, name: 'X公司', pid: 0},
{id: 2, name: '技术部', pid: 1},
{id: 3, name: '人力资源部', pid: 1},
{id: 4, name: '招聘组', pid: 3},
]
现要求对两种数据结构进行相互转换
扁平化
给定一个树状对象,要求转换成一个扁平对象
递归
在不考虑性能的情况下,递归是最快的实现方法
const result = [];
const treeToArr = (source) => {
if (!source || source.length === 0) {
return;
}
for (let item of source) {
if (item.id) {
const { id, name, pid } = item;
result.push({ id, name, pid });
}
solve(item.children, result);
}
return result;
};
treeToArr(source);
console.log(result);
展开
给定一个扁平化的对象,要求转换为一个树状对象
递归
同样最暴力的方式
let result = [];
const solve = (source, result, pid) => {
for (item of source) {
// 遍历找上一个元素的子元素
if (item.pid === pid) {
const childrenItem = { ...item, children: [] };
result.push(childrenItem);
solve(source, childrenItem.children, item.id);
}
}
};
solve(source, result, 0); // 顶层id为0
用递归的方式,每次找到一个元素A的子元素B,都要重新遍历souce去找元素B的子元素。
相比「扁平化」, 这里使用递归的复杂度看起来要更高。
使用Map优化
let result = [];
let itemMap = {};
for (item of source) {
let id = item.id;
let pid = item.pid;
itemMap[id] = {
...item,
children: itemMap[id]?.children || [], // 父元素的children可能在下面遍历子元素的时候就赋值了
};
const treeItem = itemMap[id]; // 拿到引用
if (pid === 0) {
result.push(treeItem); // 拿到顶层引用即可
} else {
// 还没遍历到他的父元素 先给个children属性
if (!itemMap[pid]) {
itemMap[pid] = {
children: [],
};
}
itemMap[pid].children.push(treeItem);
}
}
console.log(result);