【问题标题】:How to recursively generate a list of parent-child strings from an Adjacency List?如何从邻接列表递归生成父子字符串列表?
【发布时间】:2015-06-03 07:47:04
【问题描述】:

总结:

我正在尝试创建一个递归函数,该函数从邻接列表中获取数据并将其转换为点表示法。

详情:

我将此数据作为元组列表 (Python)。数据按id 排序,但这是唯一的限制。没有限制必须在子项之前列出父项:例如,项目#3 的父项可以是项#7。代数也没有(计划的)限制。

id     name     parent  |  data = [
1      A        0       |          (1, 'A', 0),
2      B        1       |          (2, 'B', 1),
3      C        1       |          ...
4      D        2       |
5      E        2       |
6      F        3       |
7      G        2       |
8      H        6       |          ...
9      I        4       |          (9, 'I', 4)]

我想以父子点表示法返回一个字符串列表:

A
A.B
A.B.D
A.B.D.I
A.B.E
A.B.G
A.C
A.C.F
A.C.F.H

请注意,每个名称都会显示 - 我发现的其他算法只会返回没有子项的项目。

我尝试过的事情:

Python 代码:

这是我目前所得到的,基于 USF 的数据结构可视化here

if len(cat_list) == 0:
    return

for item in cat_list:
    parent_id = item[0]
    name = item[1]
    children = [_x for _x in cat_list if _x[2] == parent_id]

    if len(children) == 0:
        # then we're at the end
        return name
    else:
        sub_problem = cat_list[1:]
        sub_solution = create_categories(sub_problem)
        solution = "{}.{}".format(name, sub_solution)
        print(solution)
        return solution

但这所做的只是取一个项目并一直构建它:

D.E
C.D.E
B.C.D.E
A.B.C.D.E

SQL:

如果数据存储在 SQLite 数据库中,并且可以通过以下 SQL 获取部分数据:

SELECT
    t1.name AS level1,
    t2.name as level2,
    t3.name as level3,
    t4.name as level4
FROM category AS t1
    LEFT JOIN category AS t2 ON t2.parent = t1.id
    LEFT JOIN category AS t3 ON t3.parent = t2.id
    LEFT JOIN category AS t4 ON t4.parent = t3.id
WHERE t1.name = 'A'

但这有多个问题:

  1. 不能扩展到任意深度
  2. 不返回中间深度

由于这些限制,我决定用 Python 实现代码。

研究

我查看了一堆不同的问题和网站,但没有一个给我“尤里卡”的时刻,因此我在这里问。

This question 非常相似,但在我一无所知的 vb.net 中。它也没有告诉我如何执行连接。

This question 也很相似,但我还是不懂语言。似乎Lookup 函数可能与 python dict 非常相似...

【问题讨论】:

    标签: python recursion adjacency-list


    【解决方案1】:

    数据准备步骤有点可怕,因为你的 ID 是从一个开始的,我们需要一个阻止元素 None 在位置 0:

    original = [(1, 'A', 0),
                (2, 'B', 1),
                (3, 'C', 1),
                (4, 'D', 2),
                (5, 'E', 2),
                (6, 'F', 3),
                (7, 'G', 2),
                (8, 'H', 6),
                (9, 'I', 4)]
    ids,data,parents = zip(*original)
    data =[None]+list(data)
    parents = [None]+list(parents)
    

    一旦您以正确的格式获取输入数据,此代码就会起作用:

    ids = range(1,10)
    parents = [None,0,1,1,2,2,3,2,6,4]
    data =[None,"A","B","C","D","E","F","G","H","I"]
    
    def get_parents(node):
        if not parents[node]:
            return data[node]
        return get_parents(parents[node])+data[node]
    for id in ids:
        print ".".join(list(get_parents(id)))
    >>> 
    A
    A.B
    A.C
    A.B.D
    A.B.E
    A.C.F
    A.B.G
    A.C.F.H
    A.B.D.I
    

    【讨论】:

      【解决方案2】:

      在一张纸上写下每个步骤后,我能够想出以下内容:

      def generate_category_strings(cat_list, parent_item, sent_str, retlist=[]):
          """
          Concatenates categories together and returns a list of them.
          """
          if parent_item is None:
              parent_item = cat_list[0]
              retlist.append(parent_item[1])
      
          parent_id = parent_item[0]
          parent_name = parent_item[1]
      
          if sent_str is None:
              sent_str = parent_name
      
          children = [_x for _x in cat_list if _x[2] == parent_id]
      
          if len(children) == 0:
              # base case, no children
              return ["{}.{}".format(sent_str, parent_name)]
          else:
              for child in children:
                  str_to_send = "{}.{}".format(sent_str, child[1])
                  retlist.append(str_to_send)
                  generate_category_strings(cat_list, child, str_to_send, retlist)
              return retlist
      

      在原始数据集上运行:

      data = [(1, "A", 0), (2, "B", 1), (3, "C", 1), (4, "D", 2),
              (5, "E", 2), (6, "F", 3), (7, "G", 2), (8, "H", 6),
              (9, "I", 4),
             ]
      
      a = generate_category_strings(data, None, None)
      for item in a:
          print(item)
      

      打印:

      A
      A.B
      A.B.D
      A.B.D.I
      A.B.E
      A.B.G
      A.C
      A.C.F
      A.C.F.H
      

      【讨论】:

      • 你检查我的答案了吗?顺序很重要吗?
      • 我确实看到了你的回答,谢谢。排序并不重要,因为我可以在事后对其进行排序。我想避免在生成字符串之前重塑数据。
      猜你喜欢
      • 2013-07-25
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 2010-10-28
      • 2020-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多