const list = [
{id: 1, pid: 0},
{id: 2, pid: 0},
{id: 3, pid: 0},
{id: 11, pid: 1},
{id: 12, pid: 1},
{id: 13, pid: 1},
{id: 21, pid: 2},
{id: 22, pid: 2},
{id: 23, pid: 2},
{id: 31, pid: 3},
{id: 32, pid: 3},
{id: 33, pid: 3},
{id: 111, pid: 11},
{id: 221, pid: 22},
{id: 331, pid: 33},
{id: 3331, pid: 331}
]
/*
* list [] 原数组
* id String 子id
* pid String 父id
* */
function listToTree(list, id, pid) {
let temp = {};
let tree = [];
list.forEach(item => {
temp[item[id]] = item
});
for (let i in temp) {
if (temp[i][pid] !== 0) {
if (!temp[temp[i][pid]].children) {
temp[temp[i][pid]].children = []
}
temp[temp[i][pid]].children.push(temp[i]);
} else {
tree.push(temp[i]);
}
}
return tree;
}
listToTree(list, 'id', 'pid')
/*
* tree [] 原数组
* id String 子id
* pid String 父id
* children String 父子关联字段
* */
function treeToList(tree, id, pid, children) {
let list = [];
function depAppend(node){
node.forEach(item=>{
list.push({
id:item[id],
pid:item[pid]
})
if(item[children] && item[children].length > 0){
depAppend(item[children])
}
})
}
depAppend(tree)
return list;
}
const tree = listToTree(list, 'id', 'pid');
const newList = treeToList(tree,'id', 'pid', 'children');
listToTree 使用了,复合对象中 子对象只是父对象key的引用,当子对象的值发生改变的时候,并不影响 父对象对其的引用,无论父对象是在改变之前还是之后,都可以得到最新的数据。
还有一种思路不太推荐,使用了双层for循环,时间复杂度变高
function listToTree2(oldArr){
oldArr.forEach(element => {
let parentId = element.pid;
if(parentId !== 0){
oldArr.forEach(ele => {
if(ele.id === parentId){ //当内层循环的ID== 外层循环的parendId时,(说明有children),需要往该内层id里建个children并push对应的数组;
if(!ele.children){
ele.children = [];
}
ele.children.push(element);
}
});
}
});
oldArr = oldArr.filter(ele => ele.pid === 0); //这一步是过滤,按树展开,将多余的数组剔除;
console.log(102,oldArr) //此时的数组是在原基础上补充了children;
return oldArr;
}
treeToList 核心思想就是递归。