如何处理节点的字符串以获得它们的连接?



我正在做一些关于节点树的工作,我被这个问题困住了。这个列表包含了树的所有信息:

connections = ['Module/Expr/ListComp/BinOp/Name/id/i/',
'Module/Expr/ListComp/BinOp/Sub/',
'Module/Expr/ListComp/BinOp/Num/0.5/',
'Module/Expr/ListComp/comprehension/Name/id/i/',
'Module/Expr/ListComp/comprehension/Name/id/inp/']

我需要把它转换成:

{'Module':'Expr', 'Expr':'ListComp', 'ListComp':'BinOp comprehension', 
'BinOp':'Name Sub Num', 'Name':'id', 'id':'i', 'Num':'0.5', 
'comprehension':'Name', 'Name':'id', 'id':'i inp'}

目标是将连接解析成结构{'parent':'child(s)'}的字典。为了做到这一点,我已经试过了:

rules = {}
connections_list = [[word for word in path.split("/") if word] for path in connections]
for path in connections_list:
for i, word in enumerate(path):
same_level = [y[i+1] for y in connections_list if len(connections_list) > i+1]
if same_level:
unique_on_level = list(set(same_level))
rules.update({word:" ".join(unique_on_level)})
else:
pass
break
print(rules)

输出:

{'Module': 'Expr',
'Expr': 'ListComp',
'ListComp': 'BinOp comprehension',
'BinOp': 'Num Sub Name'}

我无法想出这样做的方法,这里的问题发生在最后一个节点周围,但我不知道如何解决它,任何关于如何解决这个问题的想法?

首先创建父节点到子节点的映射,然后删除副本。

rules = {}
for connection in connections:
parts = connection.rstrip("/").split("/")
for parent, child in zip(parts, parts[1:]):
if parent not in rules:
rules[parent] = []
rules[parent].append(child)
rules = {k: " ".join({}.fromkeys(v)) for k, v in rules.items()}

根据@wim的回答和评论,我认为这应该可行:

from collections import defaultdict
rule_data = defaultdict(set)
for connection in connections:
parts = connection.rstrip("/").split("/")
for level, (parent, child) in enumerate(zip(parts, parts[1:])):
rule_data[level, parent].add(child)
rules = [
(parent, " ".join(sorted(children)))
for (_level, parent), children in rule_data.items()
]

指出:

  • 使用set会丢弃子进程的顺序;如果它很重要,我们可以使用dict(或者,为了与旧版本的Python兼容,使用OrderedDict):

    • rule_data = defaultdict(dict)
    • rule_data[level, parent][child] = None
    • (parent, " ".join(children))
  • 为了输出的稳定性,我对子进程进行排序,这样单元测试就可以很容易地工作,因此任何下游处理都不会看到虚假的变化。

  • 正如@Prune所指出的,这似乎不是数据的自然表示:

    • 你最终想要实现什么?
    • 这里的rule_data中间变量在进一步处理中可能比最终形式更有用…
    • 如果任何连接包含空格,输出将是不明确的。
connections = ['Module/Expr/ListComp/BinOp/Name/id/i/',
'Module/Expr/ListComp/BinOp/Sub/',
'Module/Expr/ListComp/BinOp/Num/0.5/',
'Module/Expr/ListComp/comprehension/Name/id/i/',
'Module/Expr/ListComp/comprehension/Name/id/inp/']
splitted_conns = [conn.strip('/').split('/') for conn in connections]
res = {}
for conn in splitted_conns:
for root, child in zip(conn[:-1], conn[1:]):
res[root] = res.get(root, set()) | {child}
print(res)

输出:

{"模块":{"Expr"},"Expr":{"ListComp"},"ListComp":{"BinOp","理解"},"BinOp":{"子"、"Num","名字"},"名字":{"id"},"id":{"输入","我"},"Num":{"0.5"},"理解":{'名字'}}

像这样?您期望的输出包含重复的节点"id",我想这是一个错误,它不是吗?

关于解决方案,我决定为每个组un子使用一个集合,因此我们可以避免在其名称中包含空格的节点失败。此外,使用集合很容易避免重复。如果要将每个集合转换为空格分隔的字符串,可以尝试这样做:

{k: ' '.join(v) for k, v in res.items()}

最新更新