实现树形数据根据末节点value回溯至根节点的label拼接功能?

给一个 树结构 如何根据 末级节点信息 组装 末级到根节点的信息
比如 下面示例 根据value值1-2 返回拼接的自身和父级的label值 节点1/节点1-2

const treeData = [{
        label: "节点1",
        value: "1",
        children: [{
            label: "节点1-1",
            value: "1-1",
        }, {
            label: "节点1-2",
            value: "1-2",
        }]
    },
    {
        label: "节点2",
        value: "2",
        children: [{
            label: "节点2-1",
            value: "2-1",
        }]
    }
]

不知道啥思路

阅读 1.5k
avatarAI BotBETA

为了实现从末节点回溯至根节点并拼接 label 的功能,你可以使用递归函数来遍历树结构。以下是一个可能的实现方式:

function findPathByValue(tree, targetValue, path = []) {
    // 遍历当前节点的所有子节点
    for (let node of tree) {
        // 将当前节点的label添加到路径中
        path.push(node.label);

        // 如果当前节点的value等于目标值,则返回从根到当前节点的路径
        if (node.value === targetValue) {
            return path.reverse().join('/'); // 反转并拼接成字符串
        }

        // 如果当前节点有子节点,则递归查找
        if (node.children && node.children.length > 0) {
            const result = findPathByValue(node.children, targetValue, path);
            if (result) {
                return result; // 如果子树中找到了结果,则返回
            }
        }

        // 如果当前节点不是目标节点且子树中也没有找到,则从路径中移除当前节点
        path.pop();
    }

    // 如果没有找到目标值,则返回null
    return null;
}

// 使用示例
const treeData = [
    {
        label: "节点1",
        value: "1",
        children: [
            {
                label: "节点1-1",
                value: "1-1",
            },
            {
                label: "节点1-2",
                value: "1-2",
            }
        ]
    },
    {
        label: "节点2",
        value: "2",
        children: [
            {
                label: "节点2-1",
                value: "2-1",
            }
        ]
    }
];

console.log(findPathByValue(treeData, '1-2')); // 输出: 节点1/节点1-2

这个函数首先遍历给定的树结构,当找到一个节点的 value 与目标值匹配时,它会将当前路径(从根节点开始到该节点)反转并拼接成一个字符串。如果当前节点不是目标节点,且它有子节点,则函数会递归地在其子节点中继续查找。如果遍历完整棵树都没有找到目标值,则函数返回 null

注意,这里使用了 path.reverse().join('/') 来反转路径数组并将其元素用 / 连接起来,因为我们是从根节点开始构建路径的,但在最终输出时需要将其转换为从末节点到根节点的顺序。

5 个回答

你这个只有根节点->叶子节点的关系,没有叶子节点到->根节点的关系,所以从叶子节点向上遍历是行不通的。
但是我教你一招,你可以把数据喂给树组件,然后在树节点的点击事件中拿到树组件的node对象,他这个是有parent的信息的,就可以从叶子节点->root节点去遍历了,我用的是TDesign,ElementUI也是一样的道理
image.png

image.png

js 代码

function getPathOfValue(array, value, path = []) {
    for (let item of array ?? []) {

        // 计算当前节点全路径数组
        let itemPath = path.concat(item.label)

        // 若当前节点值,为所寻值,则连接路径数组并返回
        if (item.value === value)
            return itemPath.join('/')

        // 否则搜寻子数组(若有)。若某子孙匹配,则返回其路径
        const ret = getPathOfValue(item.children, value, itemPath)
        if (ret) return ret;
    }
}

使用

getPathOfValue(treeData, '2') // '节点2'
getPathOfValue(treeData, '2-1') // '节点2/节点2-1'
getPathOfValue(treeData, '2-2') // undefined

回答:你采用对象数组形式存储,在后续从叶子节点到根节点的名称拼接时无法通过叶子节点找到父节点,所以有两种办法,第一种是在最初时为每个对象添加一个新属性:fullPath,最初采用递归遍历即可为每个节点添加到该属性,后续直接使用即可;第二种则是手动根据层次规律和唯一值去挨个遍历得到fullPath了,这个会和你的数据形式有关

树形数据遍历,调整为[{},{}....]格式,每个节点增加一个id,parent_id;
第一级节点id是treeData的index_x,parent_id等于0;
children节点的id是children迭代的index_j,parent_id为上一级节点id;
递归迭代拼接得到完成节点信息,直到parent_id为0为止

const newData = [
    {
        label: "节点1",
        value: "1",
        id:index_x,
        parent_id:0
    },
    {
        label: "节点1-1",
        value: "1-1",
        parentId:index_x,
        id:index_j
    },
    {
        label: "节点1-2",
        value: "1-2",
        parentId:index_x,
        id:index_j
    }......
]

最简单粗暴的就是递归了,我给你一个。
第一个参数就是要遍历的某一个节点,第二个是要查找的值
function find(node,svalue){

    //找到了返回对应节点的label
    if(node.value == svalue){
        return node.label;
    }
    //没找到就检查是否有子节点,有就循环遍历找
    if(node.children){
        for(let i=0; i<node.children.length; i++){
            //递归检查每一个子节点
            let rs = find(node.children[i], svalue);
            if( rs != null){
                //我这里的null检查是因为人为构造了一个null根节点返回结果要去掉
                if(node.label != null){
                    return node.label +'/' + rs;
                }else{
                    return rs;
                }
            }
        }
    }
    return null;
}
//这里构造了一个根节点,值都是空的,子节点用你的数组
let str = find({label:null,value:null,children:treeData}, '1-2');
console.log(str);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题