js中如何从tree数据中找出某一项以及父级和祖先级

  • js中如何从tree数据中找出某一项以及父级和祖先级
    • 递归方法
    • 迭代方法:
    • 深度优先搜索(DFS)
    • 广度优先搜索(BFS)
  • 扩展: js中迭代方法主要有哪些

js中如何从tree数据中找出某一项以及父级和祖先级

在JavaScript中,你可以使用递归方法和迭代方法来从树形数据结构中找到某一项以及其父级和祖先级。下面我会分别介绍这两种方法。

递归方法

递归方法是一种自身调用的方法,在处理树形数据结构时非常常见。下面是一个示例函数,使用递归方法找到某一项以及其父级和祖先级:

function findItemRecursive(tree, itemId, path = []) {for (const item of tree) {if (item.id === itemId) {// 找到目标项return [...path, item];}if (item.children && item.children.length > 0) {const result = findItemRecursive(item.children, itemId, [...path, item]);if (result) {// 子树中找到目标项return result;}}}// 未找到目标项return null;
}

使用方式如下:

const tree = [{id: 1,name: 'Item 1',children: [{id: 2,name: 'Item 2',children: [{id: 3,name: 'Item 3',children: []},{id: 4,name: 'Item 4',children: []}]},{id: 5,name: 'Item 5',children: []}]}
];const itemId = 3;
const result = findItemRecursive(tree, itemId);
console.log(result); // 输出 [ { id: 1, name: 'Item 1', ... }, { id: 2, name: 'Item 2', ... }, { id: 3, name: 'Item 3', ... } ]

迭代方法:

迭代方法使用循环来遍历树形数据结构,通过栈或队列来保存待处理的节点。

下面是一个示例函数,使用迭代方法找到某一项以及其父级和祖先级:

function findItemIterative(tree, itemId) {const stack = [...tree];while (stack.length > 0) {const item = stack.pop();if (item.id === itemId) {// 找到目标项return item;}if (item.children && item.children.length > 0) {stack.push(...item.children.map(child => ({ ...child, path: [...item.path, item] })));}}// 未找到目标项return null;
}

使用方式与递归方法类似:

const tree = [{id: 1,name: 'Item 1',children: [{id: 2,name: 'Item 2',children: [{id: 3,name: 'Item 3',children: []},{id: 4,name: 'Item 4',children: []}]},{id: 5,name: 'Item 5',children: []}]}
];const itemId = 3;
const result = findItemIterative(tree, itemId);
console.log(result); // 输出 { id: 3, name: 'Item 3', ... }

这就是从树形数据结构中找出某一项以及父级和祖先级的两种常见方法:递归方法和迭代方法。你可以根据自己的需求选择其中一种来实现。

更多详细内容,请微信搜索“前端爱好者戳我 查看

在JavaScript中,遍历和查找树形数据结构的方法除了递归之外,还有深度优先搜索(DFS)和广度优先搜索(BFS)等。

广度优先搜索(BFS)和深度优先搜索(DFS)是两种常用的图遍历算法,主要用于解决图或树中的搜索问题。

BFS适用于需要获取最短路径的情况,因为它按层级遍历,保证了在搜索到目标节点时,已经遍历过的节点数量最少。

DFS适用于需要遍历整个图或树的情况,但在找到目标节点时,并不能保证是最短路径。

需要注意的是,在实现中,BFS通常会使用队列来存储待访问的节点,而DFS则可以使用递归或栈来存储待访问的节点。

选择使用BFS还是DFS取决于具体问题的需求和图结构的特点。如果要找到最短路径或者确定两个节点之间的最短距离,BFS通常是更好的选择。而对于遍历整个图或树以查找一种可能的解决方案,DFS可能更适合。

下面举例说明如何使用DFS和BFS来查找树中的某一项以及它的父级和祖先级:

深度优先搜索(DFS)

深度优先搜索从起始节点开始,沿着一条路径一直深入到没有未访问节点为止,然后回溯到前一个节点,继续探索其他路径,直到所有路径都被探索完毕。

DFS的过程如下:

  1. 选择一个起始节点,并将其标记为已访问。
  2. 访问该节点。
  3. 选择一个与当前节点相邻且未访问过的节点,将其标记为已访问。
  4. 重复步骤2和3,直到不存在未访问的相邻节点。
  5. 回溯到前一个节点,继续探索其他路径。

DFS适用于需要遍历整个图或树的情况,但在找到目标节点时,并不能保证是最短路径。

function dfs(node, target, path = []) {if(node.data === target) {return path.concat(node);}if(node.children) {for(let child of node.children) {let result = dfs(child, target, path);if(result) {return result;}}}return null;
}let tree = {data: 'root',children: [{data: 'child1',children: [{data: 'grandchild1',},{data: 'child1-1',children: [{data: 'grandchild1-1',},{data: 'child1-1-1',children: [{data: 'grandchild1-1-1',},],},],},],},{data: 'child2',},],
};let target = 'child1';
let result = dfs(tree, target);
console.log(result); // [ { data: 'root', children: [ [ [Object], [Object] ] ] }, { data: 'child1', children: [ [Object] ] } ]

在上述DFS例子中,我们通过遍历每个子节点并递归调用dfs函数,直到找到目标节点。如果找到目标,我们返回路径。

广度优先搜索(BFS)

广度优先搜索从起始节点开始,逐层遍历图中的节点,先访问离起始节点最近的节点,然后再逐渐向外扩展。在搜索时使用队列来存储待访问的节点,保证按照层级顺序访问节点。

BFS的过程如下:

  1. 选择一个起始节点,并将其入队。
  2. 从队列中取出一个节点,访问该节点。
  3. 将该节点的未访问过的邻居节点入队。
  4. 重复步骤2和3,直到队列为空,即所有节点都被访问。

BFS适用于需要获取最短路径的情况,因为它按层级遍历,保证了在搜索到目标节点时,已经遍历过的节点数量最少。

function bfs(root, target) {const queue = [root];const path = [];while(queue.length) {let node = queue.shift(); path.push(node);   if(node.data === target) { return path;}   if(node.children) { for(let child of node.children) { queue.push(child); } }  }  return null; 
}let tree = {data: 'root',children: [{data: 'child1',children: [{data: 'grandchild1',},],},{data: 'child2',},],
};let target = 'child1';
let result = bfs(tree, target);
console.log(result); // [ { data: 'root', children: [ [ [Object], [Object] ] ] }, { data: 'child1', children: [ [Object] ] } ]

在上述BFS例子中,我们通过队列来存储待处理的节点,一层一层向下搜索,直到找到目标节点。如果找到目标,我们返回路径。

注意,这两种方法都返回的是找到的目标节点以及它的父级节点,但并不直接返回祖先级节点。要获取祖先级节点,可以在遍历过程中对每个节点的父级进行记录,或者在创建树的时候每个节点都保存一个指向父节点的引用。

扩展: js中迭代方法主要有哪些

在JavaScript中,有许多用于迭代数据的内置方法。以下是一些常用的:

  1. forEach(): 这个方法用于数组中的每个元素执行一次提供的函数。
let arr = [1, 2, 3, 4, 5];
arr.forEach(function(item, index) {console.log(item); // 对数组中的每个元素执行此操作
});
  1. map(): 这个方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后的返回值。
let arr = [1, 2, 3, 4, 5];
let newArr = arr.map(function(item) {return item * 2; // 将数组中的每个元素乘以2
});
  1. filter(): 这个方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
let arr = [1, 2, 3, 4, 5];
let newArr = arr.filter(function(item) {return item > 2; // 创建一个新数组,包含原数组中大于2的所有元素
});
  1. reduce(): 这个方法对累加器和数组中的每个元素(从左到右)应用一个函数,将其减少为单个值。
let arr = [1, 2, 3, 4, 5];
let sum = arr.reduce(function(prev, curr) {return prev + curr; // 将数组中的所有元素相加
}, 0); // 初始值为0
  1. reduceRight(): 这个方法和 reduce() 类似,但是从右到左执行。
  2. find(): 这个方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
let arr = [1, 2, 3, 4, 5];
let found = arr.find(function(item) {return item > 2; // 返回第一个大于2的元素
});
  1. findIndex(): 这个方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回 -1。
  2. some(): 这个方法检查数组中是否有至少一个元素通过由提供的函数实现的测试。如果有,则返回 true;否则返回 false。
  3. every(): 这个方法检查数组的所有元素是否都通过了由提供的函数实现的测试。如果所有元素都通过测试,则返回 true;否则返回 false。
  4. includes(): 这个方法判断一个数组是否包含一个指定的值,根据情况,如果需要返回 true 或 false。

以上就是JavaScript中常用的迭代方法。它们可以帮助你以各种方式处理和操作数组和可迭代对象。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云服务器基于Centos创建个人云盘实践经验分享

文章目录 安装运行Cloudreve安装ossfscentos更换yum源 配置ossfs挂载oss存储配置开机启动 配置cloudreve推荐阅读 安装运行Cloudreve 执行如下命令,下载cloudreve安装包。 wget https://labfileapp.oss-cn-hangzhou.aliyuncs.com/cloudreve_3.3.1_linux_amd64.tar…

C#/WPF 设置和启动Windows屏保程序

前言 我们平时电脑启动的屏保程序其本质也是应用程序,只是后缀名为.scr。所以我们只需要把应用程序后缀改为.scr,然后右键选择安装即可启动我们自己的屏保程序。 屏保注册表参数 设置电脑屏保参数,在个性化设置>锁屏界面>屏幕保护程序设…

Qt/QML编程之路:slider(34)

滑条slider,有时也成为进度条progressbar,在GUI界面中也是经常用到的。 import QtQuick 2.9 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.2ApplicationWindow {id:rootvisible: truewidth: 1920height: 720//title: qsTr("Hello World&q…

C#使用Stopwatch实现执行耗时及性能监测

Stopwatch类提供一组方法和属性,一般用来测量代码运行消耗时间,以便获取更多代码运行性能上的数据。以下主要介绍C#中用Stopwatch实现执行耗时及性能监测的方法。 1、Stopwatch简介 1)命名空间 using System.Diagnostics; 2)字段 字段 字…

rabbitmq-java基础详解

一、rabbitmq是什么? 1、MQ定义 MQ(Message Queue)消息队列 主要解决:异步处理、应用解耦、流量削峰等问题,是分布式系统的重要组件,从而实现高性能,高可用,可伸缩和最终一致性的架…

c#之枚举类型和结构体

(一般如果取值范围有效,使用枚举,几个类型组成了一个新的类型使用结构体) 1. 枚举 namespace 枚举类型 {enum GameState{//枚举类型中的每一个值,都是一个整数,默认为int类型Pause3,//默认值为0Failed2,//默认值为1Success7,//默认值为2Start8//默认值为3}class Program{st…

Unity面试笔记:Unity常见关键词概念

Unity面试笔记:Unity常见关键词概念 Invoke 延迟函数 和 Coroutine协程 和 Thread线程帧缓冲区(Frame buffer)颜色缓冲区(Color buffer)深度缓冲区(Depth buffer)模板缓冲区(Stencil…

如何从命令行运行testng.xml?

目录 创建一个新的java项目并从命令行运行testng.xml 使用命令行运行XML文件 从命令行运行现有maven项目的XML文件 在这篇文章中,我们将使用命令行运行testng.xml。有多种场景需要使用命令行工具运行testng.xml。也许您已经创建了一个maven项目,现在想…

运筹说 第97期|非线性规划-一维搜索

第二节 一维搜索 通过上期学习,大家已经了解了非线性规划的基本内容,那么如何求解一个非线性规划问题呢?本期小编就带大家来学习用于求解单变量无约束极值问题的方法——一维搜索,该方法也是后面求解更复杂问题的基础。 一、引入…

FinalShell连接虚拟机2024/1/16

目录 1.右键虚拟机桌面空白处,选择打开终端,在终端中输入ifconfig命令,查看Linux系统的IP地址:复制。 2.打开FinalShell,点击(1)号文件夹打开连接管理器,点击(2)号选择…

Angular系列教程之zone.js和NgZone

文章目录 什么是zone.jsZone的工作原理Zone的常见用途NgZone:Angular中的zone.js使用NgZone使用NgZone执行代码使用NgZone外部检测 结论 什么是zone.js 在Angular中,zone.js是一个非常重要的库,它为我们提供了一种跟踪和管理异步操作的机制。…

vue中引入sass、scss

常规步骤 1. 创建项目 使用vue cli 脚手架工具创建项目 vue create xxxx2. 创建全局样式文件 全局样式变量 路径:/assets/styles/variables.scss //flex 布局变量 $--flex-direction: ("row", "column"); $--flex-position: ("start"…

排序嘉年华———归并排序

文章目录 一.归并是什么?题目一:合并有序数组题目二:合并有序链表 二.归并排序1.递归式归并2.非递归式的归并排序 一.归并是什么? 相信朋友们应该做过一类题,合并两个有序数组,在链表里也有合并两个单链表…

liunx安装redis

安装redis 1.向Xftp7上传Redis压缩包 进行解压:tar -zxvf redis-6.0.8.tar.gz 解压后预编译: cd redis-6.0.8 make 创建文件: mkdir -p /opt/redis 安装到指定目录: make install PREFIX/opt/redis 进入安装文件 bin 目录:cd /opt/redis/bin ./redis-se…

Angular系列教程之依赖注入详解

文章目录 引言依赖注入基础依赖注入的基本概念依赖注入的原理 依赖注入实践依赖注入注意事项 引言 Angular作为一款流行的前端框架,提供了许多优秀的功能和特性,其中之一就是依赖注入(Dependency Injection)。依赖注入是一种设计…

IP定位技术在网络安全行业的探索

随着互联网的普及和深入生活,网络安全问题日益受到人们的关注。作为网络安全领域的重要技术,IP定位技术正逐渐成为行业研究的热点。本文将深入探讨IP定位技术在网络安全行业的应用和探索。 一、IP定位技术的概述 IP定位技术是通过IP地址来确定设备地理位…

Github 2FA验证的解决方法

当前使用GitHub需要启用 2FA 验证,也就是除了账号密码外还有一个实时码,需要额外输入这个正确的实时码才能开启 2FA 验证和后续登陆。 浏览器插件 这是目前我在使用的方法。在浏览器中添加一个叫做Authenticator的插件,传送地址:…

单表查询 -- MySQL(3)

目录 题目: 创建表: 问题(17个): 1、显示所有职工的基本信息。 2、查询所有职工所属部门的部门号,不显示重复的部门号。 3、求出所有职工的人数。 4、列出最高工资和最低工资。 5、列出职工…

5 个被低估的开源项目

文章目录 1.集算器 -数据处理2. Firecamp - 邮递员替代方案3.Keploy——后端 测试4. Hanko - 密钥验证5. Zrok - Ngrok 类固醇 长话短说 本文列出了五个不太受欢迎的优秀项目,您应该尝试一下。🔥 这些工具旨在改进数据处理、API 开发、后端测试、身份验…

GO——gin中间件和路由

中间件 参考:https://learnku.com/articles/66234 结构 中间件是函数中间件函数被放在调用链上调用链的末尾是路由path对应的函数 执行过程 net/http包调用到gin的serverHTTP 参考:go/pkg/mod/github.com/gin-gonic/ginv1.7.7/gin.go:506 通过path找到…