有一个扁平化的数组数据,表示一个组织结构的成员信息,每个成员都有一个唯一的
id
,一个指向其父成员的parentId
(根成员的parentId
可能是null
或某个特定的值,比如"0"
),以及成员的其他信息。目标是将扁平的数据列表转换成一个树形结构。在这个列表中,每个项目都有一个唯一的id
和一个可能指向其父项目的parentId
。
方法实现
// 处理树形数据的方法
handleTree(data, idKey, parentIdKey = 'parentId', childrenKey = 'children') {
// 用于存储节点数据的Map,以idKey为键
const nodeMap = new Map();
// 用于存储根节点的数组
const rootNodes = [];
// 遍历数据,构建nodeMap并找到根节点
data.forEach(node => {
// 将节点添加到nodeMap中,并初始化children为空数组
nodeMap.set(node[idKey], { ...node, [childrenKey]: [] });
// 如果parentId为null或父节点不存在于nodeMap中,则该节点为根节点
if (node[parentIdKey] === null || !nodeMap.has(node[parentIdKey])) {
// 将根节点添加到rootNodes数组中
rootNodes.push(nodeMap.get(node[idKey]));
} else {
// 否则,将当前节点添加到其父节点的children列表中
// 获取父节点
const parentNode = nodeMap.get(node[parentIdKey]);
// 将当前节点添加到父节点的children列表中
parentNode[childrenKey].push(nodeMap.get(node[idKey]));
}
});
// 返回根节点数组,它现在包含了完整的树形结构
return rootNodes;
},
方法使用
//实例数据
const data = [
{ id: 1, parentId: null, name: "CEO" },
{ id: 2, parentId: 1, name: "CTO" },
{ id: 3, parentId: 1, name: "CFO" },
{ id: 4, parentId: 2, name: "Senior Developer" },
{ id: 5, parentId: 2, name: "Junior Developer" },
{ id: 6, parentId: 3, name: "Accountant" }
];
const tree = handleTree(data,"id");
console.log(JSON.stringify(tree, null, 2));
结果展示
[
{
"id": 1,
"parentId": null,
"name": "CEO",
"children": [
{
"id": 2,
"parentId": 1,
"name": "CTO",
"children": [
{
"id": 4,
"parentId": 2,
"name": "Senior Developer",
"children": []
},
{
"id": 5,
"parentId": 2,
"name": "Junior Developer",
"children": []
}
]
},
{
"id": 3,
"parentId": 1,
"name": "CFO",
"children": [
{
"id": 6,
"parentId": 3,
"name": "Accountant",
"children": []
}
]
}
]
}
]
代码解释
-
定义变量:
nodeMap
:一个Map
对象,用于存储每个节点。键是节点的id
,值是节点的副本,但children
属性被初始化为空数组。rootNodes
:一个数组,用于存储所有的根节点(即没有父节点的节点)。
-
遍历数据:
- 对于数据列表中的每个节点,我们首先将其添加到
nodeMap
中。这样做是为了快速查找任何节点的父节点或子节点。 - 然后,我们检查该节点的
parentId
:- 如果
parentId
为null
,或者父节点不存在于nodeMap
中(这通常意味着数据有误,但我们的代码能够处理这种情况),我们将该节点视为根节点,并将其添加到rootNodes
数组中。 - 如果
parentId
不是null
,并且父节点存在于nodeMap
中,我们将当前节点添加到其父节点的children
数组中。
- 如果
- 对于数据列表中的每个节点,我们首先将其添加到
-
返回结果:
- 最后,我们返回
rootNodes
数组。现在,这个数组包含了完整的树形结构。每个节点都有一个children
数组,其中包含了它的所有子节点(如果有的话)。
- 最后,我们返回