簡體   English   中英

如何將成對依賴轉換為多路樹

[英]how to transform pairwise dependence to multiway tree

例如,存在以下依賴性:A <-B,C <-H,B <-F,B <-G,A <-C,A <-D,A <-EI將這些依賴關系轉換為像這樣的多路樹:

      A
   / /  \ \
  B  C   D E
 /\ /
F G H

誰能有一個好的方法?

python中的解決方案。

每個依賴項都是從子項到其父項的一條邊,例如A <- B意味着節點B是節點A的子項,並且您具有從BA一條邊。 就是說,您需要一個數據結構來存儲那些節點和邊緣。

朴素的老字典

第一個解決方案是簡單的命令。 我們走吧。

首先,您必須以可用格式解析依賴關系。 我提出了一種格式(父級,子級)和列表解析來解析字符串( 這很容易用任何高級語言翻譯 ):

def get_deps(dep_strings):
    """Return  list of tuples (parent, child). Very rudimentary."""
    return [tuple(dep_list) for dep_string in dep_strings.split(",") for dep_list in [dep_string.strip().split("<--")]]

其次,您必須遍歷依賴關系以構建樹( 這是算法的核心,並且易於翻譯成任何高級語言 ):

def parse_to_dict(dep_strings):
    deps = get_deps(dep_strings)
    # the dict will take associate to every parent its "children dictionaries"
    d = {}
    for (p, c) in deps:
        if p not in d: # parent has not yet been seen
            d[p] = {}
        if c not in d: # child has not yet been seen
            d[c] = {} # child is a leaf, until it becomes possibly a parent
        d[p][c] = d[c] # hang the child to its parent.

    # the dict has a key for every node, and the value is its "children dictonaries".
    # usually, we don't need this direct access, thus we remove all non root elements
    for _, c  in deps:
        del d[c]

    return d

特定於Python

由於為每個未知節點創建一個空的dict很麻煩,因此您可以使用defaultdictdict.setdefault使其更具可讀性。

...
d = defaultdict(dict) # will create an empty dict for every missing key
for (p, c) in deps:
    d[p][c] = d[c] # hang the child to its parent, create dicts on demand.

要么

...
d = {}
for (p, c) in deps:
    d.setdefault(p, {}) # will create an empty dict if this key is missiing
    d.setdefault(c, {})
    d[p][c] = d[c] # hang the child to its parent, create dicts on demand.

請注意, dict.setdefault更靈活,因為它可以接受參數,如您將在后面看到的。

定制樹

如果要構建自定義樹,則必須創建一個Node類,例如:

class Node():
    """A very simple node class"""
    def __init__(self, id):
        self.__id = id
        self.__children = []

    def add(self, n):
        self.__children.append(n)

    def __str__(self):
        if self.__children:
            return "Node {} [{}]".format(self.__id, ", ".join(str(c) for c in self.__children))
        else:
            return "Leaf {}".format(self.__id)

創建樹就像使用字典一樣簡單:

...
# we still need a dict
d = {}
for (p, c) in deps:
    d.setdefault(p, Node(p)) # we need to build a node with an id,
    d.setdefault(c, Node(c)) #  hence defaultdict is not the right tool
    d[p].add(d[c])

不同方法的輸出

# dict
{'A': {'B': {'F': {}, 'G': {}}, 'C': {'H': {}}, 'D': {}, 'E': {}}}
# defaultdict
defaultdict(<class 'dict'>,
            {'A': {'B': {'F': {}, 'G': {}}, 'C': {'H': {}}, 'D': {}, 'E': {}}})
# dict.setdefault
{'A': {'B': {'F': {}, 'G': {}}, 'C': {'H': {}}, 'D': {}, 'E': {}}}
# Node
Node A [Node B [Leaf F, Leaf G], Node C [Leaf H], Leaf D, Leaf E]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM