【问题标题】:find all possible paths in a tree in python在python中找到树中所有可能的路径
【发布时间】:2023-03-03 09:29:21
【问题描述】:

我正在尝试创建一个包含树中所有可能路径的列表。我有以下结构(来自 DB 的子集):

text = """
1,Product1,INVOICE_FEE,
3,Product3,INVOICE_FEE,
7,Product7,DEFAULT,
2,Product2,DEFAULT,7
4,Product4,DEFAULT,7
5,Product5,DEFAULT,2
"""

其中的列是:ID、产品名称、发票类型、对父 ID 的引用。 我想创建包含所有可能路径的列表,如示例中所示:

[[Product1],[Product3],[Product7,Product2,Product5],[Product7,Product4]]

我做以下事情:

lines = [ l.strip() for l in text.strip().splitlines() ]
hierarchy = [ tuple(l.split(',')) for l in lines ]

parents = defaultdict(list)
for p in hierarchy:
    parents[p[3]].append(p)

创建树然后我想找到所有路径:

def pathsMet(parents, node=''):
    childNodes = parents.get(node)
    if not childNodes:
        return []
    paths = []
    for ID, productName, invoiceType, parentID in childNodes:
        paths.append([productName] + pathsMet(parents, ID))
    return paths

print(pathsMet(parents))

我得到的结果如下:

[['FeeCashFlow1'], ['FeeCashFlow3'], ['PrincipalCashFlow7', ['AmortisationCashFlow3', ['AmortisationCashFlow2']], ['AmortisationCashFlow4']]]

如何更正代码以获得以下输出:

[['FeeCashFlow1'], ['FeeCashFlow3'], ['PrincipalCashFlow7', 'AmortisationCashFlow3', 'AmortisationCashFlow2'], ['PrincipalCashFlow7','AmortisationCashFlow4']]

【问题讨论】:

    标签: python algorithm recursion path tree


    【解决方案1】:

    您可以通过首先构建数据节点树然后遍历所有分支来构建路径列表来做到这一点:

    text = """
    1,Product1,INVOICE_FEE,
    3,Product3,INVOICE_FEE,
    7,Product7,DEFAULT,
    2,Product2,DEFAULT,7
    4,Product4,DEFAULT,7
    5,Product5,DEFAULT,2
    """
    
    data  = [ line.split(",") for line in text.split("\n") if line.strip() ]
    keys  = { k:name for k,name,*_ in data }  # to get names from keys
    tree  = { k:{} for k in keys }            # initial tree structure with all keys
    root  = tree[""] = dict()                 # tree root
    for k,_,_,parent in data: 
        tree[parent].update({k:tree[k]})      # connect children to their parent
    
    nodes = [[k] for k in root]  # cumulative paths of keys
    paths = []                   # list of paths by name
    while nodes:
        kPath = nodes.pop(0)
        subs  = tree[kPath[-1]]                         # get children
        if subs: nodes.extend(kPath+[k] for k in subs)  # accumulate nodes
        else   : paths.append([keys[k] for k in kPath]) # return path if leaf node
    

    输出:

    print(paths)
    [['Product1'], ['Product3'], ['Product7', 'Product4'], ['Product7', 'Product2', 'Product5']]
    

    【讨论】:

      【解决方案2】:

      您的代码似乎是正确的,只是您将整个列表附加到 paths 变量,而不是列表元素。

      试试这个修改:

      def pathsMet(parents, node=''):
          childNodes = parents.get(node)
          if not childNodes:
              return [[]]
          paths = []
          for ID, productName, invoiceType, parentID in childNodes:
              for p in pathsMet(parents, ID):
                  paths.append([productName] + p)
          return paths
      

      【讨论】:

      • 您有一些建议如何避免插入重复的路径?
      猜你喜欢
      • 1970-01-01
      • 2017-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-14
      • 2014-11-08
      • 2017-07-31
      相关资源
      最近更新 更多