工作开发中遇到人员管理或者菜单管理等需求时,会遇到树形数据操作的问题,这里提供两个通用的工具,用于生成对应结构.
平转树
1
2
3
4
5
6
7
8
9
#
def lto_tree(items, ckey='children', fkey='father_id', key='id'):
''' 平转树 (! 注意这里修改原对象, 请深拷贝或避免反复调用) '''
for item in items:
item.setdefault(ckey, [])
father_id = item.get(fkey)
father = father_id and next((father for father in items if father[key] == father_id), None) # 找爸爸
father and father.setdefault(ckey, []).append(item)
return [item for item in items if not item.get(fkey)]
参数解释
- ckey : 子节点的名称
- fkey : 本节点对应的父节点的主键
- key : 本节点的主键
调用方式
1
2
3
4
5
6
7
8
9
10
11
12
# 常规
dicts = [{"pk":1}, {"pk":2, "fpk":1}, {"pk":3, "fpk":2}]
combination_level(dicts, ckey="child", fkey="fpk", key="pk")
# [{'pk': 1, 'child': [{'pk': 2, 'fpk': 1, 'child': [{'pk': 3, 'fpk': 2, 'child': []}]}]}]
combination_level(dicts, ckey="child", fkey="fpk", key="pk") # 调用第二次
# [{'pk': 1, 'child': [{'pk': 2, 'fpk': 1, 'child': [{'pk': 3, 'fpk': 2, 'child': []}, {'pk': 3, 'fpk': 2, 'child': []}]}, {'pk': 2, 'fpk': 1, 'child': [{'pk': 3, 'fpk': 2, 'child': []}, {'pk': 3, 'fpk': 2, 'child': []}]}]}]
# 拷贝
import copy
combination_level(copy.deepcopy(dicts), ckey="child", fkey="fpk", key="pk")
# [{'pk': 1, 'child': [{'pk': 2, 'fpk': 1, 'child': [{'pk': 3, 'fpk': 2, 'child': []}]}]}]
combination_level(copy.deepcopy(dicts), ckey="child", fkey="fpk", key="pk")
# [{'pk': 1, 'child': [{'pk': 2, 'fpk': 1, 'child': [{'pk': 3, 'fpk': 2, 'child': []}]}]}]
树转平
下探方法
1
2
3
4
5
def tree_callback(leafs, callback=None, ckey='children', root=None, level=0):
''' 下钻寻找节点 '''
for leaf in leafs:
callback(leaf, root, level + 1) # 调用方法
tree_callback(leaf.get(ckey, []), callback=callback, ckey=ckey, root=leaf, level=level + 1)
参数解释
- leafs : 传入根节点(多个),如果单根可以套层列表 tree_callback([root], …)
- ckey : 子节点的键名称
- callback : 回掉方法
- leaf : 当前节点
- root : 当前节点的父节点
- level : 当前节点所属的层级(1开始)
树转平操作
1
2
3
4
5
tree = [{'pk': 1, 'child': [{'pk': 2, 'fpk': 1, 'child': [{'pk': 3, 'fpk': 2, 'child': []}]}]}]
flat = []
tree_callback(tree, lambda leaf, *_: flat.append(leaf), ckey='child')
print(flat)
# [{'pk': 1, 'child': [{'pk': 2, 'fpk': 1, 'child': [{'pk': 3, 'fpk': 2, 'child': []}]}]}, {'pk': 2, 'fpk': 1, 'child': [{'pk': 3, 'fpk': 2, 'child': []}]}, {'pk': 3, 'fpk': 2, 'child': []}]
通过上面两个方法就可以平树互转,下探方法可以分层级操作,分根操作,分页操作等等。