一、需求
在前端业务场景中,将数组转为树型数据结构说经常会遇到的需求。
将如下数组:
let arr = [
{
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,
"children": []
},
{
"id": 3,
"name": "部门3",
"pid": 1,
"children": [
// 结果 ,,,
]
}
]
}
]
二、数组转树
递归实现
function getChildren(arr, res, pid){
for(let i of arr){
if(i.pid === pid){
let newItem = {
...i,
children: []
};
res.push(newItem);
getChildren(arr.filter(item => item.id !== i.id), newItem.children, i.id);
}
}
}
function arrayToTree(arr, pid) {
let res = [];
getChildren(arr, res, pid);
return res;
}
非递归实现
先把数据转成Map去存储,之后遍历的同时借助对象的引用,直接从Map找对应的数据做存储。
相比于递归,非递归具有更高的性能。
function arrayToTree(items) {
let res = [];
let hash = [];
for(let i of items){
const {
id, pid} = i;
if(!hash[id]){
hash[id] = {
children: []
}
}
hash[id] = {
...i,
children: hash[id]['children']
}
const item = hash[id];
if(pid === 0){
res.push(item)
}else{
if(!hash[pid]){
hash[pid] = {
children: []
}
}
hash[pid].children.push(item);
}
}
return res;
}
结果: