树形结构的快速生成
背景
相信大家都遇到过树形结构,像是文件列表、多级菜单、评论区的设计等等,我们都发现它有很多层级,第一级可以有多个,下边的每一个层级也可以有多个;有的可以设计成无限层级的,有的只能设计成两级。那么作为程序员,我觉得应该具备这种思维:程序的拓展性。就像shigen接手需求一样,上次接到了评论回复的需求,产品觉得两级回复和多级回复可以分成两期做,细心的我就发现这完全可以整成一个需求做呢。于是我一次性把之后的都做了。

我们先分析一下具体的场景:
我们常常会遇到多级文件,类似我们电脑的文件管理系统。我们可以把每个文件夹和文件抽象一下,在linux系统中,文件就包括文本文件和文件夹。OK,万物皆文件,shigen就在这里狂一下。那它们要根据什么关联起来呢,数据库怎么存储呢?

分析
目前,我们主要的解决方案是这样的。
item_list = [Item(111, "one", None, None),Item(111-1, "one", None, None),Item(222, "two", 111, None),Item(333, "three", 111, None),Item(444, "four", 333, None),Item(444-1, "four", 333, None),Item(444-2, "four", 444-1, None),]
我们只需要存储单条数据就可以,那它们的关联就需要构造函数的第三个参数pid,保存自己上一个节点的id,如果上一个节点的id(pid)是空的,OK,那它就是第一级别的。注意,第一级别的可能有多个。Item的构造方法是这样的:
class Item():def __init__(self, id: int, name: str, pid: Optional[int], children: Optional[List]):self.id = idself.name = nameself.pid = pidself.__children = children
那么,分析起来发现就是几句话,代码怎么实现呢?shigen在这里列举了两种语言的实现方式:java和python。来一起看看吧!
代码实现
Java
在来到Java这一步,我不会使用传统的递归的方式,我使用的是java8,所以我更喜欢用stream+lambda表达式,写起来异常的简洁,别人不夸优雅都不行!
Item类的定义和python代码案例的是一样的,java的定义是这样的:
@Data@AllArgsConstructorstatic class Item {private Integer id;private String name;private Integer pid;private List<Item> children;}
那怎么实现这个tree结构呢?shigen用的一个函数,仅仅三行代码,是三行!
private static List<Item> getTree(ArrayList<Item> items) {// 获得非顶级节点的数据并按照pid分组Map<Integer, List<Item>> nodeMap = items.stream().filter(item -> item.getPid() != null).collect(Collectors.groupingBy(Item::getPid));// 循环设置子节点items.forEach(item -> item.setChildren(nodeMap.get(item.id)));// 获得根节点的数据List<Item> treeNode = items.stream().filter(node -> node.getPid() == null).collect(Collectors.toList());return treeNode;}
这是一个通用的方法,我把我的代码截图也贴上来。

这边shigen也在思考把这个方法做成通用的,这样就可以作为一个工具类使用了。也欢迎伙伴们来交流一下。
python
shigen对这个案例提供了双语言的支持。但是不得不说在和java的stream对比之下,python的代码还是显得比较繁琐了。但是也是一种解决思路和参考。
def build_tree_structure(items:List[Item]) -> List[Item]:# 获得顶级节点treeNode = list(filter(lambda item: item.pid is None, items))for node in treeNode:node.children = get_children(node, items)return treeNodedef get_children(root:Item, items:List[Item]) -> Item:children = []for item in items:if item.pid == root.id:item.children = get_children(item, items)children.append(item)return children
其实这里用到了递归的方式,先获得所有的第一级节点,然后根据第一层节点的id去匹配子级的id。这样重复的步骤,就可以使用递归来实现了,递归的终止条件就是item.pid != root.id。这个代码shigen目前已经写到最简洁了,还有其它的优化思路的,也欢迎评论区交流一下。
最后贴上我的python代码实现截图:

好了,以上就是shigen和大家分享的树形结构的快速生成的全部内容了。
与shigen一起,每天不一样!
相关文章:
树形结构的快速生成
背景 相信大家都遇到过树形结构,像是文件列表、多级菜单、评论区的设计等等,我们都发现它有很多层级,第一级可以有多个,下边的每一个层级也可以有多个;有的可以设计成无限层级的,有的只能设计成两级。那么…...
Android笔记(二十七):自定义Dialog实现居中Toast
背景 记录实现符合项目需求的Toast弹窗 具体实现 class MyTipDialog private constructor(val context: Activity): Dialog(context, R.style.MyTipTheme) {val resId ObservableField(0)private val mainHandler Handler(Looper.getMainLooper())init {setCanceledOnTouc…...
css实现文字的渐变,适合大屏
1 在全局写一个全局样式,文字渐变 2 在组件中使用 CSS3利用-webkit-background-clip: text;实现文字渐变效果_css如何把盒子底部的文字变成透明渐变_I俩月亮的博客-CSDN博客 CSS 如何实现文字渐变色 ?_css字体颜色渐变_一个水瓶座程序猿.的博客-CSDN博客…...
软考高级系统架构设计师系列论文八十七:论企业应用集成
软考高级系统架构设计师系列论文八十七:论企业应用集成 一、企业应用集成相关知识点二、摘要三、正文四、总结一、企业应用集成相关知识点 软考高级系统架构设计师系列之:企业集成平台技术的应用和架构设计二、摘要 本文讨论了某公司的应用系统集成项目。某公司为了应对市场变…...
C++设计模式之适配器模式
一、适配器模式 适配器模式(Adapter Pattern)是一种结构型设计模式,用于将一个类的接口转换成另一个类所期望的接口,以便两个类能够协同工作。 适配器模式可以解决现有类接口与所需接口不匹配的问题,使得原本因接口不…...
山西电力市场日前价格预测【2023-08-24】
日前价格预测 预测明日(2023-08-24)山西电力市场全天平均日前电价为319.98元/MWh。其中,最高日前电价为370.78元/MWh,预计出现在19: 30。最低日前电价为272.42元/MWh,预计出现在12: 45。 价差方向预测 1: 实…...
一文速学-让神经网络不再神秘,一天速学神经网络基础(一)
前言 思索了很久到底要不要出深度学习内容,毕竟在数学建模专栏里边的机器学习内容还有一大半算法没有更新,很多坑都没有填满,而且现在深度学习的文章和学习课程都十分的多,我考虑了很久决定还是得出神经网络系列文章,…...
百度Q2财报:营收341亿元实现加速增长,净利润高速增长44%,增长强劲全线重构
北京时间8月22日,百度发布了截至2023年6月30日的第二季度未经审计的财务报告。第二季度,百度实现营收341亿元,同比增长15%;归属百度的净利润(non-GAAP)达到80亿元,同比增长44%。营收和利润双双实…...
ARM DIY(二)配置晶振频率
文章目录 前言串口乱码问题定位内核修改晶振频率uboot 修改晶振频率番外篇 前言 上篇文章《ARM DIY 硬件调试》介绍了 DIY ARM 板的基础硬件焊接,包括电源、SOC、SD 卡座等,板子已经可以跑起来了。 但是发现串口乱码,今天就来解决串口乱码问…...
高等数学:线性代数-第三章
文章目录 第3章 矩阵的初等变换与线性方程组3.1 矩阵的初等变换3.2 矩阵的秩3.3 方程组的解 第3章 矩阵的初等变换与线性方程组 3.1 矩阵的初等变换 矩阵的初等变换 下面三种变换称为矩阵的初等变换 对换两行(列),记作 r i ↔ r j ( c i …...
深入理解 SQL 注入攻击原理与防御措施
系列文章目录 文章目录 系列文章目录前言一、SQL 注入的原理二、防御 SQL 注入攻击的措施1. 使用参数化查询2.输入验证与过滤3.最小权限原则4.不要动态拼接 SQL5.ORM 框架6.转义特殊字符三、实例演示总结前言 SQL 注入是一种常见的网络攻击方式,攻击者通过在输入框等用户交互…...
QT5.12.12通过ODBC连接到GBase 8s数据库(CentOS)
本示例使用的环境如下: 硬件平台:x86_64(amd64)操作系统:CentOS 7.8 2003数据库版本(含CSDK):GBase 8s V8.8 3.0.0_1 为什么使用QT 5.12.10?该版本包含QODBC。 1&#…...
爱校对发布全新PDF校对工具,为用户带来更为便捷的校正体验
随着数字化文档使用的普及,PDF格式已经成为最为广泛使用的文件格式之一。为满足广大用户对于高效、准确PDF文档校对的需求,爱校对团队经过深入研发,正式推出全新的PDF校对工具! 这一全新工具针对PDF文件格式进行了深度优化&#…...
记录protocol buffers Mac安装
使用brew安装最新的protobuf 在Mac 上安装,使用brew 可以安装最新的protobuf。这个也比较简单,简单说一下。 首先先检查一下是否安装了brew。如果没有安装brew的话,请先安装brew.可以通过brew --version来检查 使用brew install protobuf 来…...
基于Jenkins自动打包并部署docker、PHP环境,ansible部署-------从小白到大神之路之学习运维第86天
第四阶段提升 时 间:2023年8月23日 参加人:全班人员 内 容: 基于Jenkins部署docker、PHP环境 目录 一、环境部署 (一)实验环境,服务器设置 (二)所有主机关闭防火墙和selinu…...
【附安装包】Midas Civil2019安装教程
软件下载 软件:Midas Civil版本:2019语言:简体中文大小:868.36M安装环境:Win11/Win10/Win8/Win7硬件要求:CPU2.5GHz 内存4G(或更高)下载通道①百度网盘丨64位下载链接:https://pan.…...
Apache StreamPark系列教程第一篇——安装和体验
一、StreamPark介绍 实时即未来,在实时处理流域 Apache Spark 和 Apache Flink 是一个伟大的进步,尤其是Apache Flink被普遍认为是下一代大数据流计算引擎, 我们在使用 Flink & Spark 时发现从编程模型, 启动配置到运维管理都有很多可以抽象共用的地方, 我们将一些好的经验…...
mysql replace insert update delete
目录 mysql replace && insert && update && delete replace mysql replace && insert && update && delete replace 我们在使用数据库时可能会经常遇到这种情况。如果一个表在一个字段上建立了唯一索引,当我们再向…...
实现SSM简易商城项目的商品查询功能
实现SSM简易商城项目的商品查询功能 介绍 在SSM(SpringSpringMVCMyBatis)框架下,我们可以轻松地实现一个简易商城项目。本博客将重点介绍如何实现商品查询功能,帮助读者了解并掌握该功能的开发过程。 步骤 1. 创建数据库表 首…...
视频批量剪辑矩阵分发系统源码开源分享----基于PHP语言
批量剪辑视频矩阵分发: 短视频seo主要基于抖音短视频平台,为企业实现多账号管理,视频分发,视频批量剪辑,抖音小程序搭建,企业私域转化等,本文主要介绍短视频矩阵系统抖音小程序开发详细及注意事…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...
