列表list转树形结构(python/golang/js/php)

2023-11-13

1. 原数据

id parent_id name
1 0 A
2 1 AA
3 1 AB
4 3 ABA
5 3 ABB
6 3 ABC
7 1 AC
8 7 ACA
9 8 ACAA
10 8 ACAB
data = [
	{id: 1, parent_id: 0, name: "A"},
	{id: 2, parent_id: 1, name: "AA"},
	{id: 3, parent_id: 1, name: "AB"},
	{id: 4, parent_id: 3, name: "ABA"},
	{id: 5, parent_id: 3, name: "ABB"},
	{id: 6, parent_id: 3, name: "ABC"},
	{id: 7, parent_id: 1, name: "AC"},
	{id: 8, parent_id: 7, name: "ACA"},
	{id: 9, parent_id: 8, name: "ACAA"},
	{id: 10, parent_id: 8, name: "ACAB"},
]

2. 利用对象内存共享生成嵌套结构

2.1 算法原理

算法原理即流程图

2.2 算法实现

2.2.1 JS

function list_to_tree(data) {
	/**
	* @data: 由id和parent_id组成的树形结构二维数据, 元数据中id必须大于0
	*/
	res = {};
	for (let i = 0; i < data.length; i++) {
	    row = data[i];
	    // 此行代码用以统一根节点的paren_id, 跟节点的parent_id 可以为 0 或 null
	    row.parent_id = row.parent_id ? row.parent_id : 0
		if (res[row.id]) {
			Object.assign(res[row.id], {id: row.id, text: row.name});
	    } else {
			res[row.id] = {id: row.id, text: row.name, children: []};
	    }
	    if (res[row.parent_id]) {
	        res[row.parent_id].children.push(res[row.id]);
	    } else {
			res[row.parent_id] = {children: [res[row.id]]};
	    }
	}
	return res[0].children
}

2.2.2 Python

def list_to_tree(data):
    res = {}
    for v in data:
        v["parent_id"] = v["parent_id"] if v["parent_id"] else 0
        res.setdefault(v["id"], v).update(v)
        res.setdefault(v["parent_id"], {}).setdefault("children", []).append(res.get(v["id"], v))
    return res[0]["children"]

在这里插入图片描述

2.2.3 go

func listToTree(data []map[string]interface{}) []map[string]interface{} {
	res := make(map[int]map[string]interface{})
	for _, v := range data {
		id := v["id"].(int)
		parentID := v["parent_id"].(int)
		if res[id] != nil {
			v["children"] = res[id]["children"]
			res[id] = v
		} else {
			v["children"] = []map[string]interface{}{}
			res[id] = v
		}
		if res[parentID] != nil {
			res[parentID]["children"] = append(
				res[parentID]["children"].([]map[string]interface{}),
				res[id],
			)
		} else {
			res[parentID] = map[string]interface{}{
				"children": []map[string]interface{}{
					res[id],
				},
			}
		}
	}
	return res[0]["children"].([]map[string]interface{})
}

2.2.4 php

function listToTree($list) {
    $res = [];
    foreach ($list as &$v) {
        $id = $v['id'];
        $parentId = $v['parent_id'];
        //构造map给parent_id查找追加用
        if (isset($res[$id])) {
            $v['child'] = &$res[$id]['child'];//child放到v里边
            $res[$id] = $v;
        } else {
            $v['child'] = [];
            $res[$id] = $v;
        }
        //追加带child的自己到parent_id的child数组中
        if (isset($res[$parentId])) {
            $res[$parentId]['child'][] = &$res[$id];
        } else {
            $res[$parentId] = ['child' => [&$res[$id]]];
        }
    }
    return $res[0]['child'];
}

$data = [
  ['id'=> 1, 'parent_id' => 0, 'name' => "A"],
  ['id'=> 2, 'parent_id' => 1, 'name' => "AA"],
  ['id'=> 3, 'parent_id' => 1, 'name' => "AB"],
  ['id'=> 4, 'parent_id' => 3, 'name' => "ABA"],
  ['id'=> 5, 'parent_id' => 3, 'name' => "ABB"],
  ['id'=> 6, 'parent_id' => 3, 'name' => "ABC"],
  ['id'=> 7, 'parent_id' => 1, 'name' => "AC"],
  ['id'=> 8, 'parent_id' => 7, 'name' => "ACA"],
  ['id'=> 9, 'parent_id' => 8, 'name' => "ACAA"],
  ['id'=> 10, 'parent_id' => 8, 'name' => "ACAB"],
];

$res = listToTree($data);

2.3 运行结果

[
	{id: 1, text: "A", children: [
		{id: 2, text: "AA", children: []},
		{id: 3, text: "AB", children: [
			{id: 4, text: "ABA", children: []},
			{id: 5, text: "ABB", children: []},
			{id: 6, text: "ABC", children: []}
		]},
		{id: 7, text: "AC", children: [
			{id: 8, text: "ACA", children: [
				{id: 9, text: "ACAA", children: []},
				{id: 10, text: "ACAB", children: []}
			]}
		]}
	]}
]

3. 递归

3.1 算法实现

3.1.1 python

def list_to_tree2(list_data, parent_id=0):
    res = []
    for v in list_data:
        if v['parent_id'] == parent_id:
            v['children'] = get_tree_recursive(list_data, v['id'])
            res.append(v)
    return res

4. 运算效率对比

4.1 python

s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
i = 0
data = []
for v1 in s:
    i += 1
    data.append({'id': i, 'parent_id': 0, 'name': v1})
    p1 = i
    for v2 in s:
        i += 1
        data.append({'id': i, 'parent_id': p1, 'name': v1+v2})
        p2 = i
        for v3 in s:
            i += 1
            data.append({'id': i, 'parent_id': p2, 'name': v1+v2+v3})
len(data)

生成18278条三层嵌套数据结构

在这里插入图片描述
如上图所示, 递归版耗时18s, 而循环版仅耗时25ms

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

列表list转树形结构(python/golang/js/php) 的相关文章

随机推荐

  • 【torch】如何把把几个 tensor 连接起来?(含源代码)

    一 cat 在 PyTorch 中 要向一个 tensor 中添加元素 你通常需要创建一个新的 tensor 然后将元素添加到新的 tensor 中 PyTorch tensors 是不可变的 所以不能像列表一样直接追加元素 以下是如何实现
  • keytool 错误: java.io.IOException: Keystore was tampered with, or password was incorrect

    这里需要输入的密码不是证书的密码执行keytool import keystore file 这个命令提示需要输入密码 输入 changeit 信任证书 OK
  • opencv 通过网络连接工业相机_相机标定与测距

    0 概述 硬件 Realsense D435i 含imu AprilTag或棋盘格标定板 本文均使用棋盘格 说明 本文非手把手教你如何教程 需要一定的ROS基础和D435i相机调试基础 当然玩过其他相机也可以 写作过程参考了部分作者成果 如
  • 函数式编程—柯里化

    纯函数的作用和优势 1 可以安心的编写和使用 2 写的时候保证了函数的纯度 只是单纯实现自己的业务逻辑即可 不需要关心传入的内容是如何获得的或者依赖其他的外部变量是否已经发生了修改 3 在用的时候 确定输入的内容不会被任意篡改 并且自己确定
  • 玩具蛇

    include
  • 数据库SQLite

    数据库SQLite 了解最轻巧的数据库SQLite SQLite 是一款轻型的数据库 占用资源非常低 它的源代码不受版权限制 能够支持Windows Linux Unix等等主流的操作系统 同时能够跟很多程序语言相结合 比如 Tcl C P
  • 29 KVM管理系统资源-调整虚拟CPU绑定关系

    文章目录 29 KVM管理系统资源 调整虚拟CPU绑定关系 29 1 概述 29 2 操作步骤 29 KVM管理系统资源 调整虚拟CPU绑定关系 29 1 概述 把虚拟机的vCPU绑定在物理CPU上 即vCPU只在绑定的物理CPU上调度 在
  • 2-问过 chatgpt 的问题(天马行空想问什么问什么)

    目录 一 信号序列中大部分为 0 时 FFT 运算复杂度的计算 1 当fft运算时 大部分信号点为0的情况下 对fft的运算时间会有影响吗 2 大部分信号点为0的情况下 fft的运算复杂度计算 3 这里的时间复杂度 O N log
  • HTML5语音合成功能

    这篇文章主要介绍了HTML5语音合成功能的实现代码 本文通过实例代码给大家介绍的非常详细 具有一定的参考借鉴价值 需要的朋友参考下吧 可将该代码复制到chrome控制台中体验 let msg new SpeechSynthesisUtter
  • this和super

    this this总是置于当前对象的成员类作区分 this是当前对象的引用 就是说当前用构造函数建的对象是谁 这个this就代表谁 它是一个引用 this 总是指向自己本事 super 子类在重写了父类的方法后 常常还需要使用到父类中被重写
  • do while循环语句的学习以及练习

    今天学的是do while循环语句 先执行循环体 直到条件的表达式为false 与while循环语句的区别 while语句先判断条件 满足时执行循环体 do while语句先执行循环体 满足条件在执行 语法 do 循环体 while 条件
  • kinova-jaco2使用Moveit!控制真实机械臂抓取固定点物体

    kinova jaco2使用Moveit 控制真实机械臂抓取固定点物体 一 机械臂坐标系 坐标系方向 位姿方向 轴的起始点 二 启动机械臂和Moveit 三 实现抓取 python代码 python文件建议直接用python启动 四 遇到的
  • react hook之useMemo

    useMemo的作用 Pass a create function and an array of dependencies useMemo will only recompute the memoized value when one o
  • LogisticRegression(逻辑回归)

    LogisticRegression定义 logistic回归 是一种广义的线性回归分析模型 常用于数据挖掘 疾病自动诊断 经济预测等领域 例如 探讨引发疾病的危险因素 并根据危险因素预测疾病发生的概率等 以胃癌病情分析为例 选择两组人群
  • SVG转为Png

    1 pom中引入maven依赖
  • 自定义实现OAuth2.0 授权码模式

    文章目录 OAuth2 0 授权码模式 实践 依赖知识 术语 授权码流程 认证服务器 拉起请求用户授权页面 用户手动授权 提交授权 生成code 下发Token 第三方应用 收到code并请求Token 访问受保护的资源 项目结构 Tomc
  • 类EMD的“信号分解方法”及MATLAB实现(第四篇)——VMD

    重头戏来了 在以往的应用经验里 VMD方法在众多模态分解方法中可以说是非常好的 从催更力度上看 这个方法也是格外受关注 笔者决定加快进度快一些写完这个方法 十月份了有些同学要开始做毕设 希望这篇文能帮上忙 1 VMD 变分模态分解 的概念
  • poj1338【丑数·DP】

    我记得这道题以前写过 而且是写出来了 DP吧 然后现在想了好久 没想出来 然后考虑一下递推 mdzz 直接就是让之前的这个每次乘以2 3 5就好了嘛 然后每轮取最小 include
  • jquery form表单.serialize()序列化后中文乱码问题原因及解决decodeURIComponent

    jquery form表单 serialize 序列化后中文乱码问题原因及解决 原因 serialize 自动调用了encodeURIComponent方法将数据编码了 解决方法 调用decodeURIComponent XXX true
  • 列表list转树形结构(python/golang/js/php)

    文章目录 1 原数据 2 利用对象内存共享生成嵌套结构 2 1 算法原理 2 2 算法实现 2 2 1 JS 2 2 2 Python 2 2 3 go 2 2 4 php 2 3 运行结果 3 递归 3 1 算法实现 3 1 1 pyth