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

1. 原数据

idparent_idname
10A
21AA
31AB
43ABA
53ABB
63ABC
71AC
87ACA
98ACAA
108ACAB
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

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值