[英]How to Process Strings of Nodes to get their Connections?
我正在对节点树做一些工作,但我遇到了这个问题。 此列表包含树的所有信息:
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)
使用 output:
{'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))
我对孩子进行排序是为了 output 的稳定性,以便单元测试可以轻松工作,因此任何下游处理都不会看到虚假变化。
正如@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)
output:
{'Module': {'Expr'}, 'Expr': {'ListComp'}, 'ListComp': {'BinOp', 'comprehension'}, 'BinOp': {'Sub', 'Num', 'Name '},'名称':{'id'},'id':{'inp','i'},'Num':{'0.5'},'理解':{'Name'}}
像这样的东西? 您预期的 output 包含重复的节点“id”,我想这是一个错误,不是吗?
关于解决方案,我决定为每个子组使用一个集合,这样我们就可以避免节点名称中包含空格的失败。 而且,with set 很容易避免重复。 如果你想在一个空格分隔的字符串中转换每个集合,你可以试试这个:
{k: ' '.join(v) for k, v in res.items()}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.