背景
后台返回扁平化的数组,需要处理为有关联( pid 父节点 id )的树状结构
let arr = [
{ id: 2, name: "中国", pid: 1 },
{ id: 3, name: "美国", pid: 1 },
{ id: 4, name: "洛杉矶", pid: 3 },
{ id: 8, name: "洛杉矶 pid 3", pid: 3 },
{ id: 5, name: "北京", pid: 4 },
{ id: 1, name: "全球", pid: 0 },
{ id: 6, name: "父节点不存在", pid: 7 }
];
目标结果

实现方法
- 递归
/**
* 递归查找,获取children
* data: 数组
* pid: 父节点 id
*/
const getChildren = (data, result, pid) => {
for (const item of data) {
if (item.pid === pid) {
const newItem = { ...item, children: [] };
result.push(newItem);
getChildren(data, newItem.children, item.id); // 递归获取 children ,父节点 id 是 item.id
}
}
};
// 转换方法
const arrayToTree = (data, pid) => {
const result = [];
getChildren(data, result, pid);
return result;
};
- 通过对象
引用特性,通过 key 快速读取 value
// 方法二: 通过 object 引用特性,将数组转换为 object 结构,,读取快
const arrayToTree2 = (data) => {
let result = [];
let itemObj = {};
// 遍历数组,存储到对象中
for (let item of data) {
itemObj[item.id] = { ...item, children: [] };
}
console.log("itemObj: ", itemObj);
for (let item of data) {
let id = item.id;
let pid = item.pid;
if (pid === 0) {
// 根
result.push(itemObj[id]); // result 只需要 push 根元素
} else {
if (!itemObj[pid]) {
console.log("父节点不存在:", pid); // 7
itemObj[pid] = { children: [] };
}
// 通过对象取出,放入对象中的children中
itemObj[pid].children.push(itemObj[id]);
}
}
console.log("itemObj2: ", itemObj);
console.log("过程原数组不变 data: ", data);
return result;
};