[英]python find sub tree minimum and maximum value
我有一棵帶有節點的樹,在每個節點中我都有 id、name、nodes、roles、parent_id 和 type。 我需要編寫一個 function 來檢查每個節點,如果節點有角色,那么找到最小和最大持續時間或角色進入角色。 之后我需要將它與他的父母進行比較(如果不是沒有的話),如果父母的最長持續時間比它更大,那么孩子們將獲得父母/祖父母的最長持續時間。我將添加一些示例和我的預期要得到
# example 1
roles_1 = [{id: 'r1', 'duration': 4}]
roles_2 = [{id: 'r2', 'duration': 5}, {id: 'r3', 'duration': 8}]
input_tree1 = {
'nodes': [
{
'id': '1',
'name': 'org1',
'parent_id': None,
'type': 'organization',
'nodes': [
{
'id': '2',
'name': 'o_folder_1',
'org_id': '1',
'parent_id': '1',
'type': 'folder',
'roles': roles_1,
'nodes': [
{
'id': '3',
'name': 'o1_f1_project_1',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_2,
}
],
}
],
}
]
}
我有一個角色列表,每個角色列表都包含 object 的角色。 每個角色都有 id 和 duration。 在這個例子中,我的父org1有一個孩子o_folder_1和一個孫子o1_f1_project_1 ,我需要做的是檢查孫子是否有角色,如果是,我計算子樹的最小和最大持續時間,這里是 8 ,然后 go 升級計算角色,如果節點有,這里是 4.. 4 小於 8 所以我需要添加一個更新一個 max_duration 和 minimum_duration 的新字段,正如您在預期樹中看到的那樣:
expected_tree1 = {'nodes': [
{
'id': '1',
'name': 'org1',
'parent_id': None,
'type': 'organization',
'nodes': [
{
'id': '2',
'name': 'o_folder_1',
'org_id': '1',
'parent_id': '1',
'type': 'folder',
'roles': roles_1,
'min_duration': 4,
'max_duration': 4,
'nodes': [
{
'id': '3',
'name': 'o1_f1_project_1',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_2,
'min_duration': 4,
'max_duration': 8
}
],
}
],
}
]
}
正如您在此處看到的,我為每個具有正確值的節點添加了 min_duration 和 maximum_duration 的新字段。 示例 2:
# example 2
roles_1 = [{id: 'r1', 'duration': 12}]
roles_2 = [{id: 'r2', 'duration': 4}, {id: 'r3', 'duration': 2}]
roles_3 = [{id: 'r4', 'duration': 5}]
roles_4 = [{id: 'r5', 'duration': 9}]
input_tree2 = {'nodes':
[
{
'id': '1',
'name': 'org1',
'parent_id': None,
'type': 'organization',
'nodes':
[
{
'id': '2',
'name': 'o1_folder_1',
'org_id': '1',
'parent_id': '1',
'type': 'folder',
'roles': roles_1,
'min_duration': 12,
'max_duration': 12
'nodes': [
{
'id': '3',
'name': 'o1_f1_project_1',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_2,
},
{
'id': '4',
'name': 'o1_f1_project_2',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_3,
},
],
},
{
'id': '4',
'name': 'o1_folder_2',
'org_id': '1',
'parent_id': '1',
'type': 'folder',
'roles': roles_4,
'nodes': [
{
'id': '3',
'name': 'o1_f2_project1',
'nodes': [],
'org_id': '1',
'parent_id': '4',
'type': 'project',
'roles': roles_3,
}
],
},
],
}]}
預期樹 2
expected_tree2 = {'nodes':
[
{
'id': '1',
'name': 'org1',
'parent_id': None,
'type': 'organization',
'nodes':
[
{
'id': '2',
'name': 'o1_folder_1',
'org_id': '1',
'parent_id': '1',
'type': 'folder',
'roles': roles_1,
'min_duration': 12,
'max_duration': 12
'nodes': [
{
'id': '3',
'name': 'o1_f1_project_1',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_2,
'min_duration': 2,
'max_duration': 12
},
{
'id': '4',
'name': 'o1_f1_project_2',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_2,
'min_duration': 5,
'max_duration': 12
},
],
},
{
'id': '4',
'name': 'o1_folder_2',
'org_id': '1',
'parent_id': '1',
'type': 'folder',
'roles': roles_4,
'min_duration': 9,
'max_duration': 9
'nodes': [
{
'id': '3',
'name': 'o1_f2_project1',
'nodes': [],
'org_id': '1',
'parent_id': '4',
'type': 'project',
'roles': roles_3,
'min_duration': 5,
'max_duration': 9
}
],
},
],
}]}
示例 3
roles_1 = [{id: 'r1', 'duration': 18}]
roles_2 = [{id: 'r2', 'duration': 4}, {id: 'r3', 'duration': 2}]
roles_3 = [{id: 'r4', 'duration': 5}]
roles_4 = [{id: 'r5', 'duration': 9}, {id: 'r5', 'duration': 12}]
roles_5 = [{id: 'r6', 'duration': 20}]
input_tree3 = {'nodes':
[
{
'id': '1',
'name': 'org1',
'parent_id': None,
'type': 'organization',
'roles': roles_1,
'nodes':
[
{
'id': '2',
'name': 'o1_folder_1',
'org_id': '1',
'parent_id': '1',
'type': 'folder',
'roles': roles_3,
'min_duration': 12,
'max_duration': 12,
'nodes': [
{
'id': '3',
'name': 'o1_f1_project_1',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_2,
},
{
'id': '4',
'name': 'o1_f1_project_2',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_2,
},
],
},
{
'id': '4',
'name': 'o1_folder_2',
'org_id': '1',
'parent_id': '1',
'type': 'folder',
'roles': roles_5,
'nodes': [
{
'id': '3',
'name': 'o1_f2_project1',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_4,
}
],
},
],
}]}
預期樹 3
expected_tree3 = {'nodes':
[
{
'id': '1',
'name': 'org1',
'parent_id': None,
'type': 'organization',
'roles': roles_1,
'min_duration': 18,
'max_duration': 18,
'nodes':
[
{
'id': '2',
'name': 'o1_folder_1',
'org_id': '1',
'parent_id': '1',
'type': 'folder',
'roles': roles_3,
'min_duration': 5,
'max_duration': 18,
'nodes': [
{
'id': '3',
'name': 'o1_f1_project_1',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_2,
'min_duration': 2,
'max_duration': 18
},
{
'id': '4',
'name': 'o1_f1_project_2',
'nodes': [],
'org_id': '1',
'parent_id': '2',
'type': 'project',
'roles': roles_2,
'min_duration': 2,
'max_duration': 18
},
],
},
{
'id': '4',
'name': 'o1_folder_2',
'org_id': '1',
'parent_id': '1',
'type': 'folder',
'roles': roles_5,
'min_duration': 18,
'max_duration': 20,
'nodes': [
{
'id': '3',
'name': 'o1_f2_project1',
'nodes': [],
'org_id': '1',
'parent_id': '4',
'type': 'project',
'roles': roles_4,
'min_duration': 9,
'max_duration': 20
}
],
},
],
}]}
正如您在示例中看到的那樣,每次我檢查最后一個孩子是否有角色時,如果他有,它會計算最大持續時間,然后與他的父母進行比較,如果他有,如果父母有最大持續時間,它將得到它..但如果沒有,孩子只有孩子保持最長持續時間,他的父母不會受id影響,也不會得到孩子的持續時間..
假設:
實際上我試圖做的
def add_min_max_duration(tree:Dict):
for node in tree["nodes"]:
if "roles" in node.keys():
node["min_duration"] = 25
node["max_duration"] = 0
for role in node["roles"]:
node["min_duration"] = min(node["min_duration"], role.duration)
node["max_duration"] = max(node["max_duration"], role.duration)
add_min_max_duration(node)
但這不好,因為它不能與他的父母/祖父母相比。
從min_max
數據類型開始,使用+
操作組合兩個min_max
實例 -
mm1 = min_max(2,5)
mm2 = min_max(3,9)
mm3 = mm1 + mm2 # (2, 9)
我們可以這樣寫——
from math import inf
class min_max:
def __init__(self, min = +inf, max = -inf):
self.min = min
self.max = max
def __add__(self, other):
return min_max(min(self.min, other.min), max(self.max, other.max))
我們可以通過編寫 role_min_max 來計算角色的role_min_max
-
def role_min_max(role):
return iter_min_max(x["duration"] for x in role)
def iter_min_max(iterable):
r = min_max()
for value in iterable:
r = r + min_max(value, value)
return r
最后, tree_min_max
以(-Infinity, Infinity)
的默認 min_max 開始,如果存在,我們將其+
到tree["roles"]
值的role_min_max
。 對於子tree["nodes"]
的所有node
,我們使用更新后的 min_max, mm
調用tree_min_max(node, mm)
-
def tree_min_max(tree, mm = min_max()):
if "roles" in tree:
mm = mm + role_min_max(tree["roles"])
return {
"duration_min": mm.min,
"duration_max": mm.max,
**tree,
"nodes": list(tree_min_max(node, mm) for node in tree["nodes"])
}
我們將使用json
漂亮地打印新創建的樹 -
import json
print(json.dumps(tree_min_max(input_tree3), indent=2))
{
"duration_min": Infinity,
"duration_max": -Infinity,
"nodes": [
{
"duration_min": 18,
"duration_max": 18,
"id": "1",
"name": "org1",
"parent_id": null,
"type": "organization",
"roles": [
{
"id": "r1",
"duration": 18
}
],
"nodes": [
{
"duration_min": 5,
"duration_max": 18,
"id": "2",
"name": "o1_folder_1",
"org_id": "1",
"parent_id": "1",
"type": "folder",
"roles": [
{
"id": "r4",
"duration": 5
}
],
"nodes": [
{
"duration_min": 2,
"duration_max": 18,
"id": "3",
"name": "o1_f1_project_1",
"nodes": [],
"org_id": "1",
"parent_id": "2",
"type": "project",
"roles": [
{
"id": "r2",
"duration": 4
},
{
"id": "r3",
"duration": 2
}
]
},
{
"duration_min": 2,
"duration_max": 18,
"id": "4",
"name": "o1_f1_project_2",
"nodes": [],
"org_id": "1",
"parent_id": "2",
"type": "project",
"roles": [
{
"id": "r2",
"duration": 4
},
{
"id": "r3",
"duration": 2
}
]
}
]
},
{
"duration_min": 18,
"duration_max": 20,
"id": "4",
"name": "o1_folder_2",
"org_id": "1",
"parent_id": "1",
"type": "folder",
"roles": [
{
"id": "r6",
"duration": 20
}
],
"nodes": [
{
"duration_min": 9,
"duration_max": 20,
"id": "3",
"name": "o1_f2_project1",
"nodes": [],
"org_id": "1",
"parent_id": "2",
"type": "project",
"roles": [
{
"id": "r5",
"duration": 9
},
{
"id": "r5",
"duration": 12
}
]
}
]
}
]
}
]
}
請注意,您的role_*
數據應將id
放在引號中,否則字典的鍵實際上是id
function,而不是您可能想要的字符串"id"
。
另請注意,提供的輸入中有一個硬代碼"min_duration"
和"max_duration"
,我在這篇文章中將其刪除。
要從根音符中刪除duration_min
和duration_max
,我們可以添加一個特殊情況,用於節點中不存在"roles"
時 -
def tree_min_max(tree, mm = min_max()):
if "roles" in tree:
mm = mm + role_min_max(tree["roles"])
return {
"duration_min": mm.min,
"duration_max": mm.max,
**tree,
"nodes": list(tree_min_max(node, mm) for node in tree["nodes"])
}
else:
return {
**tree,
"nodes": list(tree_min_max(node, mm) for node in tree["nodes"])
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.