node和go的列表转树形, 执行速度测试对比

保证数据一致性,先生成4000条json数据到本地,然后分别读取文本执行处理

node代码

node是用midway框架

forNum1:number = 0forNum2:number = 0//执行测试async index(){// 生成菜单列表// const menuList = await this.generateMenuList([], 4000);const menuListStr = 	fs.readFileSync(this.app.getAppDir()+'/public/listJson.txt', 'utf8');const menuList = JSON.parse(menuListStr)console.time("4000条 引用类型 时间:deepTree");await this.deepTree(menuList);console.log("4000条 引用类型 时间:")console.timeEnd("4000条 引用类型 时间:deepTree");console.log("循环次数",this.forNum1)// this.logger.info("deepTree 数据", JSON.stringify(l));console.time("4000条 递归 时间:deepTree2");await this.deepTree2(menuList, null);console.timeEnd("4000条 递归 时间:deepTree2");console.log("循环次数",this.forNum2)}// 列表转树形async deepTree(list: any[]){const newList: any[] = [];const map: any = {};for (let index = 0; index < list.length; index++) {this.forNum1++const e = list[index];map[e.id] = e;}for (let index = 0; index < list.length; index++) {this.forNum1++const e = list[index];const parent = map[e.parentId];if (parent) {(parent.children || (parent.children = [])).push(e);} else {newList.push(e);}}return newList;}// 递归遍历async deepTree2(arr: any[], parentId: any) {// const loop = (parentId: any) => {//   return arr.reduce((pre, cur) => {//     this.forNum2++//     if (cur.parentId == parentId) {//       cur.children = loop(cur.id);//       pre.push(cur);//     }//     return pre;//   }, []);// }const list = []const loop = (parentId: any)=>{for (let index = 0; index < arr.length; index++) {this.forNum2++if (arr[index].parentId == parentId) {arr[index].children = loop(arr[index].id);list.push(arr[index]);}}return list}return loop(parentId);}//生成随机的菜单列表数据,给转换树形菜单使用async generateMenuList(menuList: { id: number; parentId: number | null }[] = [],maxDepth: number = 5){// 如果菜单列表长度达到1000,则停止生成if (menuList.length > maxDepth || menuList.length >= 10000) {return menuList;}const nextID = menuList.length + 1// 如果菜单列表不为空,则随机选择一个已存在的id作为parentId;否则parentId为nulllet parentId: number | null = null;if (menuList.length > 0) {parentId = menuList[Math.floor(Math.random() * menuList.length)].id;}// 将新菜单项添加到列表中menuList.push({ id:nextID, parentId });// 递归调用生成子菜单项,深度加1return this.generateMenuList( menuList, maxDepth);}

测试结果
在这里插入图片描述

go代码

go框架是goframe

var (ctx     context.ContextforNum1 = 0forNum2 = 0
)type MenuItem struct {ID       *int        `json:"id"`       // 节点的唯一标识符ParentId *int        `json:"parentId"` // 父节点的IDChildren []*MenuItem `json:"children"` // 子节点列表
}
// 遍历树
func DeepTree(strSlice []*MenuItem) interface{} {var (strMap  = make(map[int]*MenuItem)newList []*MenuItem)for i := range strSlice {node := strSlice[i]strMap[*node.ID] = nodeforNum1++}for i := range strSlice {node := strSlice[i]if *node.ParentId != 0 {strMap[*node.ParentId].Children = append(strMap[*node.ParentId].Children, node)} else {newList = append(newList, node)}forNum1++}return newList
}// 执行递归
func DeepTree2(strSlice []*MenuItem, parentId int) interface{} {var (loop func([]*MenuItem, int) []*MenuItemlist []*MenuItem)loop = func(strSlice []*MenuItem, parentId int) []*MenuItem {for i := range strSlice {forNum2++if parentId == 0 {if *(strSlice[i].ParentId) == 0 {strSlice[i].Children = loop(strSlice, *(strSlice[i].ID))list = append(list, strSlice[i])}} else if *(strSlice[i].ParentId) != 0 && *(strSlice[i].ParentId) == parentId {strSlice[i].Children = loop(strSlice, *(strSlice[i].ID))list = append(list, strSlice[i])}}return list}return loop(strSlice, parentId)
}// 生成随机菜单列表数据
func generateMenuList(menuList []*MenuItem, maxDepth int) []*MenuItem {// 如果菜单列表长度达到10000,则停止生成if len(menuList) >= maxDepth || len(menuList) >= 10000 {return menuList}nextID := len(menuList) + 1// 如果菜单列表不为空,则随机选择一个已存在的id作为parentId;否则parentId为nilvar parentId intif len(menuList) > 0 {existingItem := menuList[rand.Intn(len(menuList))]parentId = *(existingItem.ID)}// 将新菜单项添加到列表中menuList = append(menuList, &MenuItem{ID: &nextID, ParentId: &parentId})// 递归调用生成子菜单项,深度加1return generateMenuList(menuList, maxDepth)
}

开始测试

func Test(t *testing.T) {var (menuSlice []*MenuItem)//menuSlice = generateMenuList([]*MenuItem{}, 15)//gfile.PutContents("./listJson-15.txt", gconv.String(menuSlice))jsonStr := gfile.GetContents("./listJson-4000.txt")err := gconv.Scan(jsonStr, &menuSlice)if err != nil {return}startTime1 := time.Now()DeepTree(menuSlice)endTime1 := time.Now()logInfo1 := fmt.Sprintf("\n %d条 引用类型 时间:%v,循环次数:%d\n--------", len(menuSlice), endTime1.Sub(startTime1), forNum1)g.Log().Debug(ctx, logInfo1)startTime2 := time.Now()DeepTree2(menuSlice)endTime2 := time.Now()logInfo2 := fmt.Sprintf("\n %d条 引用类型 时间:%v,循环次数:%d\n--------", len(menuSlice), endTime2.Sub(startTime2), forNum2)g.Log().Debug(ctx, logInfo2)}

测试结果:
在这里插入图片描述

测试连续10次的数据
在这里插入图片描述

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

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

相关文章

密码学系列5-BLS短签名和存在不可伪造性(EUF-CMA)

本章将给出BLS短签名方案和方案的安全性证明。这个方案是很多签名方案的基础方案,学会这一个方案,也就学会了这一系列方案的安全性证明。 注:签名方案:私钥签名,公钥验证;加密方案:公钥加密,私钥解密。 论文名:Short signatures from the Weil pairing 一、BLS短签名 …

双周总结#008 - AIGC

本周参与了公司同事对 AIGC 的分享会&#xff0c;分享了 AIGC 在实际项目中的实践经验&#xff0c;以及如何进行 AIGC 的落地。内容分几项内容&#xff1a; 什么是 AIGCAIGC 能做什么AIGC 工具 以年终总结为例&#xff0c;分享了哪些过程应用了 AIGC&#xff0c;以及 AIGC 落地…

FPGA ——Verilog语法示例

FPGA ——Verilog语法示例 多模块定义条件判断 多模块定义 genvar i ;generatefor (i0 ; i<8; ii1)beginxdc xdc_u(.d1 (d1 ) ,.d2 (d2 ) ,.d3 (d3 ));end endgenerate条件判断 generate beginif(DEBUG "ON")beginila ila_u(.clk(clk),.probe0({A1,A2,A3,A4}))…

QA测试开发工程师面试题满分问答19: url请求到响应整个过程,涉及到什么技术细节

概述 当你点击鼠标发起一个请求&#xff0c;直到页面显示响应数据&#xff0c;整个过程可以详细展开为以下步骤&#xff1a; 用户点击鼠标&#xff1a;用户在浏览器中点击某个链接或按钮&#xff0c;触发请求的发起。 URL 解析&#xff1a;浏览器解析点击的链接中的 URL&…

在线音乐播放网站项目测试(selenium+Junit5)

在做完在线音乐播放网站项目之后&#xff0c;需要对项目的功能、接口进行测试&#xff0c;利用测试的工具&#xff1a;selenium以及Java的单元测试工具Junit进行测试&#xff0c;下面式测试的思维导图&#xff0c;列出该项目需要测试的所有测试用例&#xff1a; 测试结果&#…

下列程序定义了NxN的二维数组,并在主函数中自动赋值。请编写函数fun(int a[][N],int n),该函数的功能是:使数组右上半三角元素中的值乘以m。

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法完整代码和详细的解析。 题干 下列…

数据库管理-第174期 执行计划的改变竟如此复杂(20240423)

数据库管理174期 2024-04-23 数据库管理-第174期 执行计划的改变竟如此复杂&#xff08;20240423&#xff09;1 大量等待2 性能问题排查3 为什么执行计划会改变3.1 统计信息不准确3.2 表数据量过大3.3 错误索引 4 优化建议总结 数据库管理-第174期 执行计划的改变竟如此复杂&am…

【QML】State组件

State(状态)组件是一组来自默认配置的批处理更改。所有项都有一个默认状态&#xff0c;该状态定义对象和属性值的默认配置。可以通过将State项添加到states属性来定义新的状态&#xff0c;以允许项在不同的配置之间切换。 State组件的基本用法如下&#xff1a; Window {id: …

在Linux中,按上下左右键为什么变成^[[A^[[B^[[C^[[D

在Linux中&#xff0c;当你按下键盘上的箭头键时&#xff0c;通常会发送相应的转义序列给终端。这些转义序列告诉终端程序如何解释按键的含义。例如&#xff0c;按下箭头键时&#xff0c;可能会发送类似于^[[A、^[[B、^[[C、^[[D这样的序列。 这些序列的开头^[[实际上是转义字…

终端安全加强

1. 加强密码管理 对于重要数据和系统&#xff0c;必须采用复杂的密码进行保护&#xff0c;并定期更换密码。同时&#xff0c;要加强对员工密码的管理&#xff0c;确保每个员工有一个独立的账号和密码&#xff0c;并限制其使用权限。 2. 实施访问控制 对于终端设备的访问要进…

gitea是什么,与gitlab和github对比有什么特点

Gitea是一个轻量级的DevOps平台软件&#xff0c;它支持Git托管、代码审查、团队协作、软件包注册和CI/CD等功能。与GitHub和GitLab相比&#xff0c;Gitea的一个显著特点是它提供了自托管的能力&#xff0c;这意味着用户可以完全控制自己的仓库和基础设施&#xff0c;而不需要依…

【ARM Trace32(劳特巴赫) 使用介绍 12.1 -- Trace32 读写 64位地址】

请阅读【Trace32 ARM 专栏导读】 文章目录 Trace32 读写 64位地址读 64 位地址写64位地址Trace32 读写 64位地址 在使用TRACE32进行调试时,有时需要读取或操作64位的地址,特别是在处理64位的处理器或操作系统时。以下是如何在TRACE32中读取64位地址的一般方法。 读 64 位地…

MySQL行级锁——技术深度+1

引言 本文是对MySQL行级锁的学习&#xff0c;MySQL一直停留在会用的阶段&#xff0c;需要弄清楚锁和事务的原理并DEBUG查看。 PS:本文涉及到的表结构均可从https://github.com/WeiXiao-Hyy/blog中获取&#xff0c;欢迎Star&#xff01; MySQL行级锁 行级锁&#xff08;Row-…

hbase基础(三)

HBase第三天 HBase的读流程 客户端拿到一个rowkey&#xff08;首先得要知道这个rowkey存在哪个region中&#xff09;根据zk获取hbase:meta表&#xff0c;这个表中存放了region的信息&#xff0c;根据namespace、表名&#xff0c;就可以根据rowkey查看是否匹配某个region的sta…

体验升级:Shokz韶音OpenRun Pro运动耳机全面评测

在最新的产品评测中&#xff0c;我们关注了一款备受期待的运动耳机&#xff1a;基普乔格联名款Shokz韶音OpenRun Pro。这款由京东配送的耳机迅速到达并接受了我们的审查&#xff0c;旨在评估其独特的功能和性能。 音质始终是衡量耳机优劣的关键指标。韶音品牌在运动耳机行业享…

Command SwiftCompile failed with a nonzero exit code

Command SwiftCompile failed with a nonzero exit code 记录一下这个错误的一个解决方案 Xcode15.3 新建项目后 使用cocoapods&#xff0c;pod引入第三方库后报Command SwiftCompile failed with a nonzero exit code 的错误 解决方法 Target - build setting - 搜索sandbo…

爬虫ip下载

爬虫IP下载是指获取用于爬取网页数据的代理IP地址的过程。通过使用代理IP&#xff0c;可以隐藏真实的访问者IP地址&#xff0c;提高爬虫的稳定性和安全性。 通常&#xff0c;爬虫IP下载可以通过以下几种方式进行&#xff1a; 免费代理IP网站&#xff1a;有一些网站提供免费的代…

js连接抖音打印组件实现打印

js连接抖音打印组件实现打印小票 安装抖音打印组件 抖音打印组件文档&#xff1a; https://bytedance.larkoffice.com/docs/doccn2vbOOdd3KWrCd6Z93nIlvg 跟着文档案例一步步配基本上没问题&#xff0c; 打印的时候需要设置下打印机名称 export class DouyinPrint {construct…

C++11新特性 - override and final

override 关键字的应用 保证在派生类中声明的重载函数&#xff0c;与基类的虚函数有相同的签名为了减少程序运行时的错误&#xff0c;重写的虚函数都建议加上 override示例 class Base { public:virtual void Show(int x); // 虚函数 };class Derived : public Base { public…

怎么理解算力?1000P算力是什么概念?

算力&#xff0c;指计算机系统在单位时间内能够完成的计算任务量&#xff0c;它涵盖了CPU、GPU、TPU等硬件&#xff0c;每秒能处理的数据量&#xff0c;通常以“P”&#xff08;PetaFLOPS&#xff0c;即千万亿次浮点运算每秒&#xff09;为单位来衡量&#xff0c;是评估计算机性…