根据parentId将一维数组转为树结构
将乱序的一维数组根据parentId
转化为树形结构
js
let a = [
{
id: "050207",
parentId: "0502",
children: []
},
{
id: "050208",
parentId: "0502",
children: []
},
{
id: "01",
parentId: "0",
children: []
},
{
id: "02",
parentId: "0",
children: []
},
{
id: "050209",
parentId: "0502",
children: []
},
{
id: "0201",
parentId: "02",
children: []
},
{
id: "05",
parentId: "0",
children: []
},
{
id: "0501",
parentId: "05",
children: []
},
{
id: "0502",
parentId: "05",
children: []
},
{
id: "050201",
parentId: "0502",
children: []
},
{
id: "050202",
parentId: "0502",
children: []
},
{
id: "050203",
parentId: "0502",
children: []
},
{
id: "050204",
parentId: "0502",
children: []
},
{
id: "050205",
parentId: "0502",
children: []
},
{
id: "050206",
parentId: "0502",
children: []
}
]
function buildTreeOptimized(nodes) {
const nodeMap = new Map(); // 哈希表存储所有节点
const roots = []; // 存储顶层节点
const duplicates = new Set(); // 检测重复ID
// 第一次遍历: 注册所有节点 & 检测重复
for (const node of nodes) {
const id = node.id;
// 循环引用检测
if (node.id === node.parentId) {
throw new Error(`循环引用: ${node.id} -> ${node.parentId}`);
}
// 重复ID检测
if (nodeMap.has(id)) {
duplicates.add(id);
continue;
}
// 初始化子节点数组
node.children = [];
nodeMap.set(id, node);
}
// 输出重复警告
if (duplicates.size > 0) {
console.warn(`检测到重复ID: ${Array.from(duplicates).join(', ')}`);
}
// 第二次遍历: 构建树结构
for (const node of nodes) {
const { parentId } = node;
// 跳过已处理的重复节点
if (duplicates.has(node.id)) continue;
if (parentId === '0') {
roots.push(node); // 顶层节点
} else if (parentId) {
const parent = nodeMap.get(parentId);
parent ?.children.push(node); // 挂载子节点
} else {
console.warn(`独立节点 ${node.id}: parentId为空`);
}
}
return roots;
}
// 使用示例
const tree = buildTreeOptimized(a);
console.log(tree);