场景
给你一个像下面所示的一维数组,然后把他转成tree
const 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 },
]
const tree = [
{
"id": 1,
"name": "部门1",
"pid": 0,
"children": [
{
"id": 2,
"name": "部门2",
"pid": 1,
"children": []
},
{
"id": 3,
"name": "部门3",
"pid": 1,
"children": [
{
"id": 4,
"name": "部门4",
"pid": 3,
"children": [
{
"id": 5,
"name": "部门5",
"pid": 4,
"children": []
}
]
}
]
}
]
}
]
解法一
直接递归
我自己的解法
const 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 },
]
const newArr = [...arr];
const arrayToTree = (arr, data) => {
arr.forEach(item1 => {
if(item1.children){
arrayToTree(item1.children, data)
}
newArr.forEach(item2 => {
if(item2.pid === item1.id){
if(!item1.children){
item1.children = [];
}
item1.children.push(item2);
}
})
});
}
arrayToTree(arr, newArr)
const tree = arr.filter(item => item.pid === 0);
最佳解法
const 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 },
]
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);
}
}
}
const arrayToTree = (data, pid) => {
const result = [];
getChildren(data, result, pid)
return result;
}
const tree = arrayToTree(arr, 0);
解法二
利用对象的地址引用
我自己的解法
const arr = [
{id: 1, name: '部门1', pid: 0, children: []},
{id: 2, name: '部门2', pid: 1, children: []},
{id: 3, name: '部门3', pid: 1, children: []},
{id: 4, name: '部门4', pid: 3, children: []},
{id: 5, name: '部门5', pid: 4, children: []},
]
const newArr = [...arr];
arr.forEach((item1, index1) => {
newArr.forEach((item2, index2) => {
if(item2.pid === item1.id){
item1.children.push(arr[index2])
}
})
})
const tree = arr.filter(item => item.pid === 0)
最佳解法
const 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 },
]
const arrayToTree = () => {
const arrMap = {};
const result = [];
for(const item of arr){
arrMap[item.id] = {...item, children: []}
}
for(const item of arr){
const { id, pid } = item;
if(pid === 0){
result.push(arrMap[id]);
} else{
if (!arrMap[pid]) {
arrMap[pid] = {
children: [],
}
}
arrMap[pid].children.push(arrMap[id])
}
}
return result;
}
const tree = arrayToTree(arr);
比较
递归的时间复杂度是O(2^n),利用对象指针的是时间复杂度是O(2n) 从性能上看,递归消耗的消耗是比较大的
总结
每个人的实现方式都不一样,我的实现方式相比最佳解法性能上差距还是比较大的,我遍历的嵌套比较多,其实像这种利用对象地址引用的实现类似的还有链表,可以看看我的另一篇文章: 链表