树形结构和一维数组是开发中很容易碰到的情况,也是面试中很容易碰到的手撕题目
FROM
const source = [
{ id: 1, name: "张三", pid: 0 },
{ id: 2, name: "李四", pid: 1 },
{ id: 3, name: "王五", pid: 2 },
{ id: 4, name: "赵六", pid: 3 },
{ id: 5, name: "陈七", pid: 4 },
{ id: 6, name: "谢八", pid: 4 },
{ id: 7, name: "林一", pid: 1 },
{ id: 8, name: "杨二", pid: 3 },
];
TO
[
{
"id": 1,
"name": "张三",
"pid": 0,
"children": [
{
"id": 2,
"name": "李四",
"pid": 1,
"children": [
{
"id": 3,
"name": "王五",
"pid": 2,
"children": [
{
"id": 4,
"name": "赵六",
"pid": 3,
"children": [
{
"id": 5,
"name": "陈七",
"pid": 4
},
{
"id": 6,
"name": "谢八",
"pid": 4
}
]
},
{
"id": 8,
"name": "杨二",
"pid": 3
}
]
}
]
},
{
"id": 7,
"name": "林一",
"pid": 1
}
]
}
]
迭代实现
const buildTree = (root) => {
const hash = {};
const tree = [];
root.forEach((node) => {
hash[node.id] = node;
});
root.forEach((node) => {
const parent = hash[node.pid];
if (parent) {
(parent.children || (parent.children = [])).push(node);
} else {
tree.push(hash[node.id]);
}
});
return tree;
}
const tree = buildTree(source);
console.log(JSON.stringify(tree, null, 2));
递归实现
const buildTree = (root, pid = 0) => {
const tree = [];
for (const node of root) {
if (node.pid === pid) {
const children = buildTree(root, node.id);
if (children.length) {
node.children = children;
}
tree.push(node);
}
}
return tree;
};
const tree = buildTree(source);
console.log(JSON.stringify(tree, null, 2));
// 展平树状数组
const node = {
id: 0,
parentId: null,
name: "生物",
children: [
{
id: 1,
parentId: 0,
name: "动物",
children: [
{
id: 4,
parentId: 1,
name: "哺乳动物",
children: [
{
id: 8,
parentId: 4,
name: "大象",
},
{
id: 9,
parentId: 4,
name: "海豚",
},
{
id: 10,
parentId: 4,
name: "猩猩",
},
],
},
{
id: 5,
parentId: 1,
name: "卵生动物",
children: [
{
id: 11,
parentId: 5,
name: "蟒蛇",
},
{
id: 12,
parentId: 5,
name: "麻雀",
},
],
},
],
},
{
id: 2,
parentId: 0,
name: "植物",
children: [
{
id: 6,
parentId: 2,
name: "种子植物",
children: [
{
id: 111,
parentId: 6,
name: "种子植物的孩子1",
},
{
id: 112,
parentId: 6,
name: "种子植物的孩子2",
},
],
},
{
id: 7,
parentId: 2,
name: "蕨类植物",
},
],
},
{
id: 3,
parentId: 0,
name: "微生物",
},
],
};
// 展平
[
{ id: 0, parentId: null, name: "生物" },
{ id: 1, parentId: 0, name: "动物" },
{ id: 2, parentId: 0, name: "植物" },
{ id: 3, parentId: 0, name: "微生物" },
{ id: 4, parentId: 1, name: "哺乳动物" },
{ id: 5, parentId: 1, name: "卵生动物" },
{ id: 6, parentId: 2, name: "种子植物" },
{ id: 7, parentId: 2, name: "蕨类植物" },
{ id: 8, parentId: 4, name: "大象" },
{ id: 9, parentId: 4, name: "海豚" },
{ id: 10, parentId: 4, name: "猩猩" },
{ id: 11, parentId: 5, name: "蟒蛇" },
{ id: 12, parentId: 5, name: "麻雀" },
{ id: 111, parentId: 6, name: "种子植物的孩子1" },
{ id: 112, parentId: 6, name: "种子植物的孩子2" },
];
const treeToFlat = (root) => {
let res = [];
let queue = [root];
while (queue.length) {
const node = queue.shift();
res.push({
id: node.id,
parentId: node.parentId,
name: node.name,
});
if (node.children) {
for (const child of node.children) {
queue.push(child);
}
}
}
return res;
};
console.log(treeToFlat(node));