将扁平的数据转为树形结构 层级部门人数统计 递归
def get_tree_ids(tree: dict, keyword='id', child_name="children") -> list:
'''
求树的全部节点的id
方法:1、递归;2、数据库遍历parent_id查询
'''
ids = [tree[keyword]]
children = tree.get(child_name)
if children:
for child in children:
ids += get_tree_ids(child)
return ids
def find_sub_tree(tree: dict, keyword_val, keyword='id', child_name="children") -> dict | None:
'''
求子树
'''
if tree[keyword] == keyword_val:
return tree
children = tree.get(child_name)
ret = None
if children:
for child in children:
ret = find_sub_tree(child, keyword_val)
if ret:
break
return ret
case = {'id': 75, 'name': '测试用例', 'parent_id': None,
'person_num': 22, 'children': [
{'id': 76, 'name': '广告发行中心', 'parent_id': 75,
'person_num': 14, 'children': [
{'id': 77, 'name': '广告商务组', 'parent_id': 76, 'person_num': 0},
{'id': 78, 'name': '广告投放组', 'parent_id': 76, 'person_num': 5},
{'id': 79, 'name': '广告设计组', 'parent_id': 76, 'person_num': 7},
{'id': 80, 'name': '发行运营组', 'parent_id': 76,
'person_num': 1}]},
{'id': 81, 'name': '技术部', 'parent_id': 75, 'person_num': 6},
{'id': 82, 'name': '创意设计部', 'parent_id': 75, 'person_num': 0}]}
case1 = {'id': 13, 'name': 'A团队', 'parent_id': None, 'person_num': 12,
'children': [{'id': 61, 'name': '项目二', 'parent_id': 13, 'person_num': 4,
'children': [{'id': 111, 'name': '测试部门', 'parent_id': 61,
'person_num': 3, 'children': [
{'id': 10197, 'name': 'testDep0', 'parent_id': 111,
'person_num': 0, 'children': [
{'id': 10199, 'name': 'testDep0-0',
'parent_id': 10197, 'person_num': 0}]},
{'id': 10198, 'name': 'testDep1', 'parent_id': 111,
'person_num': 3, 'children': [
{'id': 10200, 'name': 'testDep1-0',
'parent_id': 10198, 'person_num': 3}]}]}]},
{'id': 62, 'name': '项目三', 'parent_id': 13, 'person_num': 4,
'children': [{'id': 64, 'name': '子项目一', 'parent_id': 62,
'person_num': 4}]}]}
小结:
1、借助指针,2个循环搞定;
2、支持无限层级的树状结构。
type T struct { domain.VOGoodsCat Children []*T } flat := func() []domain.VOGoodsCat { flat := []domain.VOGoodsCat{} for _, v := range out.List { u := domain.VOGoodsCat{} u.ParentId = v.ParentId u.CategoryId = v.CategoryId u.ParentId = v.ParentId u.Name = v.Name flat = append(flat, u) } return flat }() treeList := func() []T { // TODO 族谱树 多叉树 treeList := []T{} flatPtr := []T{} for _, i := range flat { t := T{} t.CategoryId = i.CategoryId t.ParentId = i.ParentId t.Name = i.Name t.Children = []*T{} flatPtr = append(flatPtr, t) } for m := range flatPtr { for n := range flatPtr { if flatPtr[m].CategoryId == flatPtr[n].ParentId { flatPtr[m].Children = append(flatPtr[m].Children, &flatPtr[n]) } } } for _, j := range flatPtr { if j.ParentId == -1 { treeList = append(treeList, j) } } return treeList }()
如果Children无数据,从返回空数组调整为null
[]*T -->> *[]*T nil
type T struct { domain.VOGoodsCat Children *[]*T } flat := func() []domain.VOGoodsCat { flat := []domain.VOGoodsCat{} for _, v := range out { u := domain.VOGoodsCat{} u.ParentId = v.ParentId u.CategoryId = v.CategoryId u.ParentId = v.ParentId u.Name = v.Name flat = append(flat, u) } return flat }() treeList := func() []T { // TODO 族谱树 多叉树 treeList := []T{} flatPtr := []T{} for _, i := range flat { t := T{} t.CategoryId = i.CategoryId t.ParentId = i.ParentId t.Name = i.Name t.Children = nil flatPtr = append(flatPtr, t) } for m := range flatPtr { for n := range flatPtr { if flatPtr[m].CategoryId == flatPtr[n].ParentId { if flatPtr[m].Children == nil { flatPtr[m].Children = &[]*T{} } *(flatPtr[m].Children) = append(*(flatPtr[m].Children), &flatPtr[n]) } } } for _, j := range flatPtr { if j.ParentId == -1 { treeList = append(treeList, j) } } return treeList }()
def list_to_tree(lst: list, parent_id, keyword='id', parent_name="parent_id", child_name="children") -> list:
hashmap = {}
tree = []
for data in lst:
if data[parent_name] == parent_id:
tree.append(data)
hashmap[data[keyword]] = data
for data in lst:
parent = hashmap.get(data[parent_name])
if parent is None:
continue
if parent.get(child_name) is None:
parent[child_name] = []
parent[child_name].append(data)
return tree
def list_to_tree_with_count(lst: list, parent_id, keyword='id', parent_name="parent_id", child_name="children",
num_name="person_num") -> list:
tree_list = list_to_tree(lst, parent_id, keyword=keyword, parent_name=parent_name, child_name=child_name)
'''
测试sql
SELECT u.`name`,u.create_time,c.id,c.parent_id ,c.`name`
FROM account_user u right JOIN center_company_department c ON u.dept_id=c.id WHERE
c.id IN (70200,70198,70199,70197,61,111,13,62,64,10169) ORDER BY c.id DESC,c.parent_id DESC;
'''
def sum_tree(node):
'''
求树节点的和
'''
total = 0
if num_name in node:
total = node[num_name]
if child_name in node:
for i in node[child_name]:
total += sum_tree(i)
return total
def r(node) -> None:
'''
递归
求出各个节点的后代的和
'''
node[num_name] = sum_tree(node)
if child_name in node:
for i in node[child_name]:
r(i)
return
for i in tree_list:
r(i)
return tree_list
应用场景:
层级部门人数统计
翻译
搜索
复制