sem*_*267 6 python algorithm graph python-3.x
我在编写可以读取员工/经理CSV的算法时遇到问题,并输出一个有关员工/经理关系的有向图.
我的foobar示例:给出以下CSV文件
john,
jill, john
tom, john
tim, jill
felisa, tom
ray, tom
bob, tim
jim, tim
pam, felisa
ben, ray
james, ray
mike, pam
rashad, ben
henry, james
Run Code Online (Sandbox Code Playgroud)
如何构建DiGraph,以便显示以下组织结构:
john
/ \
jill tom
/ / \
tim felisa ray
/ \ / / \
bob jim pam ben james
/ / \
mike rashad henry
Run Code Online (Sandbox Code Playgroud)
显然这是一个图形问题,但我在确定使用哪个结构时遇到问题(例如,最好是使用dict或构建自定义OrganizationalGraph对象等).任何帮助表示赞赏.
选择的语言并不重要(虽然我们可以简单地说Python是相应的[更新后的标签]),我更倾向于试图理解这类问题的基本原理(即递归与迭代,使用set()存储经理的直接报告与仅使用抽象的数据结构.最后,不,使用标准库之外的任何包都是非首发.
为了构建图表,我们获得了以下信息:
请注意,在您问题的示例csv数据中,您似乎拼错felisa了felia. 因此,这些输出不是针对您提供的实际数据,而是针对更正后的版本。首先我们解析csv文件,提取根和边列表:
import csv
with open('data.csv') as f:
f = list(csv.reader(f, skipinitialspace=True))
root, *edges = f
root = root[0]
print(root)
print(edges)
Run Code Online (Sandbox Code Playgroud)
输出:
john
[['jill', 'john'], ['tom', 'john'], ['tim', 'jill'], ['felisa', 'tom'], ['ray', 'tom'], ['bob', 'tim'], ['jim', 'tim'], ['pam', 'felisa'], ['ben', 'ray'], ['james', 'ray'], ['mike', 'pam'], ['rashad', 'ben'], ['henry', 'james']]
Run Code Online (Sandbox Code Playgroud)
我们使用defaultdictfrom collections(标准库)来表示图。我们使用key字典中的 来表示父/经理,使用value来表示孩子/员工的列表:
from collections import defaultdict
graph = defaultdict(list)
for child, parent in edges:
graph[parent].append(child)
print(graph)
Run Code Online (Sandbox Code Playgroud)
输出:
defaultdict(<class 'list'>, {'john': ['jill', 'tom'], 'jill': ['tim'], 'tom': ['felisa', 'ray'], 'tim': ['bob', 'jim'], 'felisa': ['pam'], 'ray': ['ben', 'james'], 'pam': ['mike'], 'ben': ['rashad'], 'james': ['henry']})
Run Code Online (Sandbox Code Playgroud)
这个结构让我们可以得到一个节点的子节点列表graph[node]。我们知道树的根节点是不存在于任何列表中的任何值中的节点。我们之前也保存了根。
我从字面上理解了“我如何构建一个有向图以便可以显示以下组织结构”。这是我们如何遍历此图结构以构建字符串表示的示例:
res = ''
stack = [(root, 0)]
needed_lines = defaultdict(int)
while stack:
node, level = stack.pop()
prev_level = level-4
res += '\n' + ''.join('|' if i in needed_lines else
' ' if i <= level-4 else
'-' for i in range(level)) + node
for child in graph[node]:
stack.append((child, level+4))
needed_lines[level] += len(graph[node])
needed_lines[prev_level] -=1
if needed_lines[prev_level] == 0: del needed_lines[prev_level]
print(res)
Run Code Online (Sandbox Code Playgroud)
输出:
john
|---tom
| |---ray
| | |---james
| | | |---henry
| | |---ben
| | |---rashad
| |---felisa
| |---pam
| |---mike
|---jill
|---tim
|---jim
|---bob
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
205 次 |
| 最近记录: |