将扁平的数据转为树形结构 层级部门人数统计 递归

 

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

 

 

应用场景:

层级部门人数统计

 

 

 

posted @ 2022-03-09 23:03  papering  阅读(1096)  评论(0编辑  收藏  举报