繁体   English   中英

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

[英]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中间变量可能比最终形式在进一步处理中更有用...
    • 如果任何连接包含空格,则 output 将不明确。
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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM