我使用Python字典(product_dict)来表示产品及其所有子部分的层次结构。 dict的键是唯一ID(UUID),值是Class对象,包含有关这些部分的所有信息,包括:
part.name # A string, containing the actual name of a component
part.idCode # UUID of component
part.parent # UUID of parent component
part.children # List of UUIDs of child components
part.tier # An integer that specifies its tier/level within the hierarchy
现在为了以有序的方式输出数据,我希望按层次和字母顺序对部分进行排序。对于使用树结构的分层排序,我发现这个问题的答案非常适合打印:Sorting data hierarchically。对于这个使用我的数据结构的例子,我做了一些小的修改:
class Node:
def __init__(self, article):
self.article = article
self.children = []
self.parent = None
self.name = None
def printer(self, level=0):
print ('{}{}'.format('\t' * level, self.name))
for child in self.children:
child.printer(level + 1)
class Tree:
def __init__(self):
self.nodes = {}
def push(self, article, parent, name):
if parent not in self.nodes:
self.nodes[parent] = Node(parent)
if article not in self.nodes:
self.nodes[article] = Node(article)
if parent == article:
return
self.nodes[article].name = name
self.nodes[article].parent = self.nodes[parent]
self.nodes[parent].children.append(self.nodes[article])
@property
def roots(self):
return (x for x in self.nodes.values() if not x.parent)
t = Tree()
for idCode, part in product_dict.iteritems():
t.push(idCode, part.parent, part.name)
for node in t.roots:
node.printer()
考虑到我的产品是飞机的示例,输出现在看起来如下(实际订单各不相同):
Aircraft
Systems
Subsystem 2
Subsystem 1
Subsubsystem 1.1
Engines
Airframe
Section 2
Section 1
Section 4
Section 3
但是,由于我在这个阶段对Python的理解有限,我很难在这个例程中添加字母排序(基于part.name字符串)。我理解树是如何构建的,但我没有掌握打印例程,因此无法判断在何处添加字母排序例程。
根据给定的例子,我想要的输出应该是:
Aircraft
Airframe
Section 1
Section 2
Section 3
Section 4
Engines
Systems
Subsystem 1
Subsubsystem 1.1
Subsystem 2
非常感谢任何帮助。我不遵守上面给出的分层排序方法,所以我对完全不同的方法持开放态度。
答案 0 :(得分:1)
您似乎唯一需要做的就是在打印时按名称对孩子进行排序,即
for child in sorted(self.children, key = lambda x: x.name):
child.printer(level + 1)
答案 1 :(得分:0)
给出一个层次字典:
{
UUID("71f0967f-bfd3-43d5-883e-f3c971de141f"): {
"id": UUID("71f0967f-bfd3-43d5-883e-f3c971de141f"),
"name": "D10:0:0",
"code": "r0:0:0",
"level": 0,
"parent_id": None,
},
UUID("f3dcaf21-66c9-48c5-9aae-f9ac84fc7d45"): {
"id": UUID("f3dcaf21-66c9-48c5-9aae-f9ac84fc7d45"),
"name": "D11:0:0",
"code": "r1:0:0",
"level": 1,
"parent_id": UUID("71f0967f-bfd3-43d5-883e-f3c971de141f"),
},
UUID("4c39d1e8-ba09-455c-8f76-866200531c51"): {
"id": UUID("4c39d1e8-ba09-455c-8f76-866200531c51"),
"name": "D12:0:0",
"code": "r2:0:0",
"level": 2,
"parent_id": UUID("f3dcaf21-66c9-48c5-9aae-f9ac84fc7d45"),
},
UUID("8c4e89f2-7564-417f-88ba-1cbb3f9ac23f"): {
"id": UUID("8c4e89f2-7564-417f-88ba-1cbb3f9ac23f"),
"name": "D12:0:1",
"code": "r2:0:1",
"level": 2,
"parent_id": UUID("f3dcaf21-66c9-48c5-9aae-f9ac84fc7d45"),
}, ...
}
您可以按以下顺序按键保留层次结构:
TD1 = typing.Dict[str, typing.Union[UUID, str, int, None]]
TD1Dict = typing.Dict[UUID, TD1]
def _sort_dict_hierarchy(dicts: TD1Dict, parent_id: typing.Optional[UUID] = None) -> TD1Dict:
roots = [(k, v) for k, v in dicts.items() if v['parent_id'] == parent_id]
sorted_dicts: TD1Dict = {}
for k, v in sorted(roots, key=lambda r: r[1]['name']):
sorted_dicts[k] = v
sorted_dicts.update(_sort_dict_hierarchy(dicts, v['id']))
return sorted_dicts
测试:
def create_dict_hierarchy(parent_id=None, level=0, pos=0, max_level=4):
"""Create a hierachy of dicts as we expect to be returned from oauth2."""
dicts = {}
for i in range(random.randrange(2, 4)):
uid = uuid.uuid4()
dicts[uid] = {
'id': uid,
'name': f'D1{level}:{pos}:{i}',
'code': f'r{level}:{pos}:{i}',
'level': level,
'parent_id': parent_id,
}
if level < max_level:
dicts.update(create_dict_hierarchy(uid, level+1, i, max_level))
return dicts
def test_sort_dict_hierarchy():
"""Sort dicts by nane in hirarchy."""
dicts = create_dict_hierarchy(max_level=3)
dicts_items = list(dicts.items())
random.shuffle(dicts_items)
shuffled_dicts = {k: v for k, v in dicts_items}
assert list(dicts.keys()) != list(shuffled_dicts.keys())
sorted_dicts = _sort_dict_hierarchy(shuffled_dicts)
assert list(dicts.keys()) == list(sorted_dicts.keys())