解析树形结构
733字约2分钟
2024-07-25
项目中树形结构的使用场景
业务:给定一个json树形结构,返回选中key值相邻的节点,如果同层级没有则返回父节点寻找,再没有则继续返回。
ps:本来选中只给了一个标识,如果是子节点选中,父节点也要被选中。这里就涉及到是不是最深处选中的节点。但是这个在业务中单独拎出来了,所以这里就不再写这个(虽然那个也是我写的,我当时思路是递归,子节点有选中就把父节点信息删除。)。
{
"key": "rWh9lQEXVDz-",
"pos": 1,
"children":
[
{
"key": "kuJuKOsAGttZ",
"pos": 2,
"children":
[
{
"key": "Nc41GsaSNgzIwr",
"pos": 3,
},
{
"key": "Nfgas1GSNgzIwr",
"pos": 4,
},
{
"key": "Nc41fasSNgzIwr",
"pos": 5,
}
],
},
{
"key": "w9ot_j3jbqW7",
"pos": 10,
"children":
[{
"key": "Fmvy61OnI_dA",
"pos": 11,
}],
}],
},
{
"key": "rtPONt-TYGOj",
"pos": 12,
"children":[
{
"key": "NcSNgzIwr",
"pos": 13,
},
{
"key": "sdsfasfas",
"pos": 14,
},
{
"key": "Nc41GSNgzIwr",
"pos": 15,
}
],
}
业务场景代码实现
// 最终返回处理后的数据
function findNodes(tree_arr: TreeNode[], active_key_list: string[]) {
// 使用map数据结构装每层深度的节点
const depthMap = new Map();
// 使用map数据结构装每个节点的信息,以及其父节点,和同层节点的情况下在父节点中的index值
const nodeMap = new Map()
// 递归处理数据,扁平化节点,并剔除children属性
function setMap(Node: TreeNode, depth: number = 1, parentKey?: string) {
const new_node = { ...Node }
const set_item: ActiveNode = { ...new_node }
// 存在父级节点保留key值
if (parentKey) {
set_item.parentKey = parentKey
}
delete new_node.children;
// 判断当前深度是否被存储
if (depthMap.has(depth)) {
const list = depthMap.get(depth)
var list_length = list.length
list.push({ ...set_item, parentKeyIndex: list_length })
} else {
depthMap.set(depth, [{ ...set_item, parentKeyIndex: 0 }])
}
delete set_item.children
// 保留每个节点信息
nodeMap.set(new_node.key, { ...set_item, depth, parentKeyIndex: list_length || 0 })
if (Node.children) {
for (let index = 0; index < Node.children.length; index++) {
setMap(Node.children[index], depth + 1, Node.key)
}
}
}
// 循环处理初始树形结构
for (const treeItem of tree_arr) {
setMap(treeItem)
}
// 根据选中key值循环获取节点信息
const active_info_list = active_key_list.map(active_key => {
// 获取当前节点信息
const { key, pos, parentKey, depth, parentKeyIndex } = nodeMap.get(active_key)
// 拿到同层级的节点
const node_list = depthMap.get(depth)
// 获取下个节点
const next_active = node_list[parentKeyIndex + 1]
const obj = { key, pos, } as any
// 下个节点存在
if (next_active) {
const { parentKey: next_parentKey, pos: next_pos } = next_active
// 判断是不是同层节点
if (next_parentKey !== parentKey) {
// 获取父节点列表
const parent_list = depthMap.get(depth - 1)
// 循环父节点列表获取下个父节点
for (let index = 0; index < parent_list.length; index++) {
const { key: parent_key, pos: parent_pos } = parent_list[index]
// 父节点列表下个节点一致则确定
if (parent_key == next_parentKey) {
obj.next_pos = parent_pos
break
}
}
} else {
obj.next_pos = next_pos
}
} else {
obj.next_pos = null
}
return obj
})
return active_info_list
}
归纳总结
也不知道哪个铁憨憨设置的数据结构,树形结构中的大纲内容key没有和具体内容映射。
非要搞个获取相邻节点才能得到位置距离才能根据两个节点之间的距离获取内容,受不了!!!
ps:也许这不是最好的逻辑处理代码,但是是我目前能想到了的,如果有更好的思路可以指导一下我。