JS 实现树形结构的各种操作(2)

一 数据源

        以下所有操作,都使用本数据做测试。

const oraData = [
    {
        id: "1",
        name: "动物",
        children: [
            {
                id: "1-1",
                name: "哺乳类",
                children: [
                    {
                        id: "1-1-1",
                        name: "小猫",
                        children: []
                    },
                    {
                        id: "1-1-2",
                        name: "小狗",
                        children: []
                    },
                    {
                        id: "1-1-3",
                        name: "小猪",
                        children: []
                    }
                ]
            },
            {
                id: "1-2",
                name: "鸟类",
                children: [
                    {
                        id: "1-2-1",
                        name: "燕子",
                        children: []
                    },
                    {
                        id: "1-2-2",
                        name: "喜鹊",
                        children: []
                    },
                    {
                        id: "1-2-3",
                        name: "鹦鹉",
                        children: []
                    }
                ]
            }
        ]
    },
    {
        id: "2",
        name: "水果",
        children: [
            {
                id: "2-1",
                name: "苹果",
                children: []
            },
            {
                id: "2-2",
                name: "香蕉",
                children: []
            }
        ]
    },
    {
        id: "3",
        name: "蔬菜",
        children: []
    }
];

二  遍历tree,生成序号(像文章的一级标题、二级标题)

先看结果:每个name后面的文字都生成了序号,二级标题前面也有一级标题序号。

实现源码

const createSerialNumber = (tree, parentNo = '') => {
    const result = [];
    tree.forEach((node, index) => {
        // 如果当前没有父序号,则当前序号不加点。
        let currentNo = `${index + 1}`;
        // 如果有父序号,则父序号后面加点。
        if (parentNo) {
            currentNo = `${parentNo}.${index + 1}`;
        }
        // 创建新对象
        const newNode = {
            id: node.id,
            name: `${currentNo} ${node.name}`,
        };

        // 将新节点添加到结果数组中
        result.push(newNode);

        // 如果节点有子节点,递归遍历子节点
        if (node.children && node.children.length > 0) {
            const childResult = createSerialNumber(node.children, currentNo);
            result.push(...childResult); // 将子节点的结果合并到主结果中
        }
    });
    return result;
};

console.log(createSerialNumber(oraData));

三   删除tree 节点,如果是父节点,同时需要删除子节点。

 先看结果,删除了第一个节点(id=“1”)。

实现源码

const deleteTreeNodes = (data, deleteNode) => {
    var newTree = data.filter((item) => item.id !== deleteNode)
    newTree.forEach((item) => item.children && (item.children = deleteTreeNodes(item.children, deleteNode)))
    return newTree
}

console.log(JSON.stringify(deleteTreeNodes(oraData, "1"), null, 2));

四  更新节点内容

先看结果,替换了节点id为“2-2”的内容。

                 

实现源码:

const updateTreeNode = (tree, keyToUpdate, newValue) => {
    // 遍历树的每个节点
    for (let i = 0; i < tree.length; i++) {
        const node = tree[i];
        // 检查是否找到匹配的节点
        if (node.id === keyToUpdate) {
            // 更新节点的 designItem
            node.name = newValue;
            // 如果不需要继续搜索,可以直接返回
            return tree;
        }
        // 如果节点有子节点,递归调用函数
        if (node.children && node.children.length > 0) {
            updateTreeNode(node.children, keyToUpdate, newValue);
        }
    }
    // 如果没有找到匹配的节点,返回原树
    return tree;
}

console.log(JSON.stringify(updateTreeNode(oraData, "2-2", "火龙果"), null, 2));

五  新增选择节点的同级节点

先看结果,在节点id为“3”后面新增了一个id为“4”的交通工具的节点。

实现代码:

const addSameLevelNode = (tree, newNode, targetKey) => {
    // 递归遍历树结构
    const traverse = (nodes) => {
        for (let i = 0; i < nodes.length; i++) {
            const node = nodes[i];
            // 检查当前节点是否是要添加同级节点的目标节点
            if (node.id === targetKey) {
                // 在目标节点之后添加新节点
                nodes.splice(i + 1, 0, newNode);
                // 添加完成,停止遍历
                return;
            }
            // 如果有子节点,则递归遍历子节点
            if (node.children && node.children.length > 0) {
                traverse(node.children);
            }
        }
    }

    // 开始遍历树的根节点
    traverse(tree);
}

const getNewTreeData = () => {
    const treeData = JSON.parse(JSON.stringify(oraData));
    const newNode = {id: "4", name: "交通工具", children: []}
    addSameLevelNode(treeData, newNode, "3");
    return treeData;
};

console.log(JSON.stringify(getNewTreeData(), null, 2));

六  新增选择节点的子节点 

先看结果,在【蔬菜】节点里面添加一个【番茄】的子节点。

                 

实现源码:

const addChildNode = (tree, parentId, newNode) => {
    // 遍历树的递归函数
    function traverse(node) {
        // 检查当前节点是否为目标节点
        if (node.id === parentId) {
            debugger
            // 如果目标节点有children数组,则直接添加新节点
            // 如果没有,则先创建一个children数组
            if (!Array.isArray(node.children)) {
                node.children = [];
            }
            node.children.push(newNode); // 添加新节点
            return; // 找到后退出递归
        }

        // 如果没有找到目标节点,则继续遍历子节点(如果存在)
        if (Array.isArray(node.children)) {
            for (let i = 0; i < node.children.length; i++) {
                traverse(node.children[i]);
            }
        }
    }

    // 注意:这里假设tree是一个数组,所以需要一个一个元素的遍历
    tree.map((item, index) => {
        traverse(item);
    })

}

const getChildNodes = () => {

    const treeData = JSON.parse(JSON.stringify(oraData));
    const newNode = {id: "3-1", name: "番茄", children: []};
    addChildNode(treeData, "3", newNode);
    return treeData;
};

console.log(JSON.stringify(getChildNodes(), null, 2));

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/721857.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023年中国数据库市场440亿,云数据库四强(阿里、腾讯、亚马逊、华为),本地数据库四强(Oracle、华为、微软、达梦)

近期IDC公布了中国关系型数据库市场的数据&#xff0c;整体市场276亿人民币&#xff08;38亿美元&#xff09;&#xff0c;其中公有云数据库市场175亿人民币&#xff08;24.1亿美元&#xff09;&#xff0c;备注&#xff1a;汇率按7.26计算。 关系型数据库是数据库整体市场最大…

2024年阿里巴巴全球数学竞赛首次向人工智能(AI)开放

大家好&#xff0c;我是微学AI&#xff0c;最近大家突然开始关注阿里巴巴全球数学竞赛了&#xff0c;在这个人工智能爆发的时代&#xff0c;2024年阿里巴巴全球数学竞赛首次向人工智能&#xff08;AI&#xff09;开放&#xff0c;要求参赛的AI模型在比赛前提交源代码&#xff0…

[Qt的学习日常]--常用控件3

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、显示类控…

Python武器库开发-武器库篇之SQL注入扫描器(五十九)

Python武器库开发-武器库篇之SQL注入扫描器(五十九) SQL注入漏洞简介以及危害 SQL注入漏洞是一种常见的Web应用程序漏洞&#xff0c;攻击者可以利用该漏洞在应用程序的数据库中执行恶意的SQL查询或指令。这可能导致数据泄露、数据损坏、应用程序崩溃或未经授权的访问。 SQL注…

L51--- 144. 二叉树的前序遍历(深搜)---Java版

1.题目描述 2.思路 二叉树的前序遍历遵循 根左右 &#xff08;1&#xff09;方法 preorderTraversal 输入参数: TreeNode root root是二叉树的根节点。 返回值: List 返回一个包含二叉树节点值的列表&#xff0c;这些值按照前序遍历的顺序排列。 功能: 这个方法是前序遍历的…

剖析 Kafka 消息丢失的原因

文章目录 前言一、生产者导致的消息丢失的场景场景1&#xff1a;消息太大解决方案 &#xff1a;1、减少生产者发送消息体体积2、调整参数max.request.size 场景2&#xff1a;异步发送机制解决方案 &#xff1a;1、使用带回调函数的发送方法 场景3&#xff1a;网络问题和配置不当…

React 中的 ErrorBoundary

在 React 中&#xff0c;如果不做任何控制&#xff0c;当组件出现异常时&#xff0c;React 渲染就会停止&#xff0c;页面出现白屏&#xff0c;这种体验很不好。例如当用户输入某些非法数据&#xff0c;而前端都没有进行校验&#xff0c;页面出现白屏。这种情况下&#xff0c;最…

如何训练AI大模型?熬夜爆肝整理大全

随着人工智能技术的快速发展&#xff0c;大型预训练模型在自然语言处理、计算机视觉、语音识别等领域取得了显著成果。这些模型通过在海量数据上进行预训练&#xff0c;能够捕捉到丰富的特征信息&#xff0c;为各种下游任务提供强大的支持。然而&#xff0c;训练AI大模型面临着…

20240616日志:大模型压缩方法DMS

Location: Beijing 1 大模型剪枝 Fig. 1.1大模型压缩-剪枝 剪枝的理论来源基于彩票假设&#xff08;Lottery Ticket Hypothesis&#xff09;&#xff0c;指在神经网络中存在一种稀疏连接模式&#xff0c;即仅利用网络的一小部分连接&#xff08;彩票&#xff09;就足以实现与整…

npm语义化版本和版本运算符

版本号组成 一个完整的版本号&#xff0c;由三部分组成&#xff1a;主版本号&#xff08;major&#xff09;、次版本号(minor)、修订版本号(patch)&#xff0c;简称X.Y.Z&#xff0c;具体含义&#xff1a; 主版本号&#xff08;major&#xff09;&#xff1a;项目&#xff08…

环境搭建---单机k8s

配置基础环境 关闭防火墙 [rootVM-20-14-centos ~]# systemctl stop firewalld && systemctl disable firewalld关闭selinux [rootVM-20-14-centos ~]# setenforce 0 && sed -i "s/SELINUXenforcing/SELINUXdisabled/g" /etc/selinux/config禁止s…

【Java】已解决java.lang.NullPointerException异常

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.lang.NullPointerException异常 一、问题背景 在Java编程中&#xff0c;java.lang.NullPointerException&#xff08;空指针异常&#xff09;是一种常见的运行时异常。当应…

封装音视频编解码和渲染的动态链接库编译和测试

1.动态链接库的编译 生成了以下几个文件 我们把生成的lib文件复制到lib文件夹中 其余三个文件不变动 2.进行测试看是否可以用生成的xcodec.lib库文件里的接口函数 以上是重新创建的新项目&#xff0c;导入了xcodec.lib&#xff0c;其他配置同以前项目 库测试结果 运行显示我们…

【Linux环境下Hadoop部署】— 报错“bash: myhadoop.sh: command not found“

项目场景&#xff1a; 执行 “myhadoop.sh stop” 命令。 问题描述 bash: myhadoop.sh: command not found 原因分析&#xff1a; 查看我们的系统配置&#xff0c;发现没有myhadoop.sh文件存放的路径。 解决方案&#xff1a; 1、执行 “sudo vim /etc/profile” 命令&#xff…

不入耳的蓝牙耳机平价推荐,五大爆款分析测评

开放式耳机在如今社会中已经迅速成为大家购买耳机的新趋势。它作为骨传导耳机&#xff0c;深受用户的喜爱&#xff0c;不仅可以随时感知周围环境&#xff0c;还提供了高质量的音效体验&#xff0c;对于热爱运动的人士而言&#xff0c;高品质的骨传导耳机无疑是首选。同时&#…

看完轻松解决家里灰尘毛絮多难题?除粉尘的空气净化器品牌分享

家里的空气中弥漫着灰尘和毛絮&#xff0c;让人呼吸不畅&#xff0c;也影响着家人的健康。灰尘中含有各种有害物质&#xff0c;如细菌、病毒、花粉等&#xff0c;长期吸入会导致呼吸道疾病、皮肤过敏等问题。尤其是对于有宠物、孩子、过敏人群来说&#xff0c;空气质量更是至关…

【Linux】进程间通信3——system V共享内存

1.system V进程间通信 管道通信本质是基于文件的&#xff0c;也就是说操作系统并没有为此做过多的设计工作&#xff0c;而system V IPC是操作系统特地设计的一种通信方式。但是不管怎么样&#xff0c;它们的本质都是一样的&#xff0c;都是在想尽办法让不同的进程看到同一份由操…

鸿蒙实现自定义Tabbar样式,显示数字红点提示

前言&#xff1a; DevEco Studio版本&#xff1a;4.0.0.600 Tabs的链接参考&#xff1a;OpenHarmony Tabs TabContent的链接参考&#xff1a;OpenHarmony TabContent 通过查看链接参考我们知道可以通过TabContent的tabBar来实现自定义TabBar样式&#xff08;CustomBuilder&…

SAP ABAP开发:如何读取物料主数据中的长文本?

在SAP ERP系统中&#xff0c;物料的基本描述可存储40个字符&#xff0c;见下图&#xff1a; 但长文本信息如何从系统中读取呢&#xff1f; 在SAP ABAP开发中&#xff0c;读取物料主数据&#xff08;Material Master Data&#xff09;中的基本视图&#xff08;Basic View&#…

UNetMultiLane 多车道线、车道线类型识别【训练+部署】

基于UNet 分割模型增加了检测头来识别车道线的类型&#xff08;单实线、双黄线等10种&#xff09;&#xff0c;同时可以识别出"所在车道"和"车道线类型"。 训练代码【训练练手代码】 1 数据说明 基于开源数据集 VIL100。其中数据标注了所在的六个车道的车…