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

news2025/3/15 8:37:15

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

node代码

node是用midway框架


  forNum1:number = 0
  forNum2: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为null
    let parentId: number | null = null;
    if (menuList.length > 0) {
      parentId = menuList[Math.floor(Math.random() * menuList.length)].id;
    }

    // 将新菜单项添加到列表中
    menuList.push({ id:nextID, parentId });

    // 递归调用生成子菜单项,深度加1
    return this.generateMenuList( menuList, maxDepth);
  }

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

go代码

go框架是goframe

var (
	ctx     context.Context
	forNum1 = 0
	forNum2 = 0
)

type MenuItem struct {
	ID       *int        `json:"id"`       // 节点的唯一标识符
	ParentId *int        `json:"parentId"` // 父节点的ID
	Children []*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] = node
		forNum1++
	}
	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) []*MenuItem
		list []*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为nil
	var parentId int
	if len(menuList) > 0 {
		existingItem := menuList[rand.Intn(len(menuList))]
		parentId = *(existingItem.ID)
	}

	// 将新菜单项添加到列表中
	menuList = append(menuList, &MenuItem{ID: &nextID, ParentId: &parentId})

	// 递归调用生成子菜单项,深度加1
	return 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.coloradmin.cn/o/1622682.html

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

相关文章

C++ | Leetcode C++题解之第47题全排列II

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> permuteUnique(vector<int>& nums) {dfs(nums, 0);return res;} private:vector<vector<int>> res;void dfs(vector<int> nums, int x) {if (x num…

js的算法-插入排序(直接插入排序)

插入排序 插入排序是一种简单直接的排序方法&#xff0c;其基本思想是每次将一个待排序的记录按其关键字大小插入到前面已经排好序的子序列&#xff0c;直到全部记录插入完成。由插入排序的思想可以引申出三个重要的排序算法&#xff1a; 直接插入排序、折半插入排序和希尔排序…

【书生浦语第二期实战营学习作业笔记(二)】

书生浦语第二期实战营学习作业&笔记(二) 操作文档&#xff1a;https://github.com/InternLM/Tutorial/blob/camp2/helloworld/hello_world.md 基础作业 &#xff1a; 使用 InternLM2-Chat-1.8B 模型生成 300 字的小故事&#xff1a; 八戒部署&#xff08;笔记&#xff0…

【Linux系统编程】第九弹---权限管理操作(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、目录权限 2、粘滞位 总结 1、目录权限 首先提出一个问题&#xff0c;删除一个文件需要什么权限呢&#xff1f;&#xff1f…

竞赛 基于大数据的社交平台数据爬虫舆情分析可视化系统

文章目录 0 前言1 课题背景2 实现效果**实现功能****可视化统计****web模块界面展示**3 LDA模型 4 情感分析方法**预处理**特征提取特征选择分类器选择实验 5 部分核心代码6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于大数据…

以算力深挖数据应用价值!和鲸助力北京市市场监管数据应用创新竞赛圆满收官!

历时三个多月&#xff0c;北京市市场监管数据应用创新竞赛&#xff08;以下简称“竞赛”&#xff09;圆满收官。本次竞赛旨在挖掘数据的潜在价值&#xff0c;以优化营商环境、智慧监管、高质量发展为核心议题&#xff0c;鼓励参赛者深入结合监管数据&#xff0c;开展精准而深入…

正式退役!波士顿动力Atlas宣布终止研发!

文 | BFT机器人 4月16日&#xff0c;波士顿动力在YouTube上发布了一段Atlas的最新视频&#xff0c;并宣布了Atlas终止研发的消息。 在最后的告别片段中&#xff0c;它依旧完成了奔跑、跳跃、后空翻等动作&#xff0c;甚至连摔倒在地的动作也还是熟悉的滑稽样。Atlas的退役&…

视频美颜SDK原理与实践:从算法到应用

当下&#xff0c;从社交媒体到视频通话&#xff0c;人们越来越依赖于视频美颜功能来提升自己的形象。而视频美颜SDK作为支撑这一技术的重要工具&#xff0c;其原理和实践至关重要。 一、什么是视频美颜SDK&#xff1f; 视频美颜SDK是一种软件开发工具包&#xff0c;用于集成到…

微软发布Phi-3,手机上就能跑,是时候聊聊小型语言模型了|TodayAI

微软公司最近宣布推出了其最新开发的最新AI语言模型&#xff0c;名为Phi-3。这款小型语言模型&#xff08;SLMs&#xff09;在市场上以其卓越的性能和成本效率获得关注&#xff0c;尤其在语言处理、推理、编程及数学基准测试方面表现出色&#xff0c;超越了同等规模甚至更大规模…

Matlab|含多微网租赁共享储能的配电网博弈优化调度

目录 主要内容 结果一览 下载链接 主要内容 首先利用NSGA-II算法求解三个微网的最优充放电策略并做为已知条件代入到双层调度模型中&#xff1b;然后求解双层模型&#xff0c;上层为主动配电网调度模型&#xff0c;下层包括共享储能优化模型和多微网优化调度模型&a…

SPSS软件安装包(亲测可用)

目录 一、软件简介 二、软件下载 一、软件简介 IBM SPSS Statistics是一款功能强大的统计分析软件&#xff0c;广泛应用于各种学术研究、商业决策和政府机构等领域。其强大的数据分析和可视化功能使得用户能够从数据中发现模式、预测趋势&#xff0c;并做出有根据的决策。 SPS…

《系统架构设计师教程(第2版)》第10章-软件架构的演化和维护-02-面向对象软件架构演化过程

文章目录 1. 对象演化1.1 添加一个新对象&#xff08;AO&#xff09;1.2 删除一个对象&#xff08;DO&#xff09; 2. 消息演化2.1 消息2.2 消息演化的操作2.2.1 Add Message(AM)2.2.2 Delete Message (DM)2.2.3 Swap Message Order(SMO)2.2.4 Overturn Message(OM)2.2.5 Chang…

【漏洞复现】泛微e-office系统ajax.php接口存在任意文件上传漏洞

漏洞描述 泛微e-office系统是标准、易用、快速部署上线的专业协同OA软件。泛微 E-Office 9.5版本存在代码问题漏洞,泛微e-office系统ajax.php接口存在任意文件上传漏洞 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,…

缓存神器-JetCache

序言 今天和大家聊聊阿里的一款缓存神器 JetCache。 一、缓存在开发实践中的问题 1.1 缓存方案的可扩展性问题 谈及缓存&#xff0c;其实有许多方案可供选择。例如&#xff1a;Guava Cache、Caffine、Encache、Redis 等。 这些缓存技术都能满足我们的需求&#xff0c;但现…

电商技术揭秘三十一:智能风控与反欺诈技术

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘二十八&#xff1a;安全与合规性保障 电商技术揭秘二十九&#xff1a;电商法律合规浅析 电商技术揭秘三十&#xff1a;知识产权保…

全光谱灯对人体的危害?谨记全光谱灯选购要避开的四大套路

全光谱灯对人体的危害有多大&#xff1f;近年来网上关于护眼台灯对视力有害的言论有很多&#xff0c;引发了很多人空前的关注&#xff0c;事实上这未必是一件坏事&#xff0c;因为随着护眼台灯的热度持续上涨&#xff0c;市面上浑水摸鱼的行为增多了不少&#xff0c;有着不少劣…

不要摆摊,不要开早餐店,原因如下

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 我最近开通了视频号会员专区嘛&#xff0c;专区有个问答功能可以提问&#xff0c;有个会员问了我问题&#xff0c;其中一条问答分享给大家&#xff1a; 松哥&#xff0c;突然想去兼职&#xff0c;早上卖点杂粮煎饼果…

像素着色技术在AI去衣中的深度应用与探索

在人工智能&#xff08;AI&#xff09;领域&#xff0c;图像处理技术一直是一个热门且充满挑战的研究方向。其中&#xff0c;AI去衣技术作为图像处理技术的一个分支&#xff0c;近年来引起了广大研究者和公众的广泛关注。本文将重点探讨像素着色技术在AI去衣中的重要作用&#…

深度学习图像生成在AI去衣技术中的应用与探索

随着人工智能技术的迅猛发展&#xff0c;深度学习在图像生成领域的应用越来越广泛。其中&#xff0c;AI去衣技术作为深度学习在图像处理中的一个新兴分支&#xff0c;引起了广大科研人员和公众的关注。本文将深入探讨深度学习图像生成在AI去衣技术中的作用&#xff0c;并尝试解…

那些你不知道的数据库知识:行式存储和列式存储

前几天听课&#xff0c;听到老师讲数据列式存储。 我&#x1f64b;&#x1f3fb;‍♀️&#xff1a;等等&#xff0c;what&#xff0c;什么列式存储&#xff0c;数据一行一行的展示&#xff0c;然后一行一行的存在数据库里面不就好了&#xff0c;什么叫做列式存储&#xff0c;…