【问题标题】:Generating a hierarchy from a Python list从 Python 列表生成层次结构
【发布时间】:2021-03-07 08:48:03
【问题描述】:

我正在使用 Python 3.8。

以下列表包含整数,我需要从该列表中生成层次结构:

list1 = [[15, 1], [22, 1], [23, 1], [121, 15], [101, 22], [105, 23], [106, 23], [108, 23], [155, 121], [120, 108], [19, 2], [25, 5], [33, 8], [35, 8], [28, 25], [29, 28]]

我需要这个结果(输出可以是一个列表,例如[[[1, 15, 22, 23], [15, 121], [121, 155], [22, 101], [23, 105, 106, 108], [108, 120]], [2, 19], [[5, 25], [25, 28], [28, 29]], [8, 33, 35]]):

1 ---- 15 ---- 121 ---- 155
 \---- 22 ---- 101
  \--- 23 ---- 105
        \----- 106
         \---- 108 ---- 120

2 ---- 19

5 ---- 25 ---- 28 ----- 29

8 ---- 33
 \---- 35

层次结构不包含任何重复项。同样list1 中列表的第一项不包含重复/重复的元素,但list1 中列表的第二项包含。

如何生成这种层次结构?

注意:我可以通过使用一些代码来做到这一点,但它可能会很长并且 CPU 成本可能会很高(实际列表很长)。

【问题讨论】:

  • 你能把预期的输出显示为合法的python吗?
  • “我可以通过使用一些代码来做到这一点” - 你会期待一个没有代码的答案吗??
  • @python_user,我添加了一个示例输出列表,但可能有更好的建议。
  • 为什么是 [[5, 25], [2, 28], [28, 29]] 而不是 [[5, 25], [[25, 28], [[28, 29]]]] ? @demirod
  • @python_user,我已经更正了。

标签: python python-3.x list hierarchy


【解决方案1】:

您可以尝试使用这个递归函数,它有点冗长,可以使用列表推导重新编写。 need 是您的预期输出。

list1 = [[15, 1], [22, 1], [23, 1], [121, 15], [101, 22], [105, 23], [106, 23], [108, 23], [155, 121], [120, 108], [19, 2], [25, 5], [33, 8], [35, 8], [28, 25], [29, 28]]

need = [[[1, 15, 22, 23], [15, 121], [121, 155], [22, 101], [23, 105, 106, 108], [108, 120]], [2, 19], [[5, 25], [25, 28], [28, 29]], [8, 33, 35]]

graph = {}

for y, x in list1:
    graph.setdefault(x, []).append(y)

def form_graph(graph):
    seen = set()

    def form(k, v):
        if k in seen:
            return []
        res = [[k]]
        res[-1].extend(v)
        seen.add(k)

        for i in v:
            if i in graph:
                res.extend(form(i, graph[i]))
        return res

    result = []
    for k, v in graph.items():
        temp = form(k, v)
        if temp:
            if len(temp) == 1:
                temp = temp[0]
            result.append(temp)
    return result

输出

print(form_graph(graph))
[[[1, 15, 22, 23], [15, 121], [121, 155], [22, 101], [23, 105, 106, 108], [108, 120]], [2, 19], [[5, 25], [25, 28], [28, 29]], [8, 33, 35]]

print(need == form_graph(graph))
True

如果您觉得这很有用,请点赞并接受答案。

【讨论】:

  • 它可以工作并且输出比我在第一篇文章中的示例输出更有用。我不能投票,因为声誉分数低于 15。
【解决方案2】:

您可以使用广度优先搜索:

from collections import deque, defaultdict
list1 = [[15, 1], [22, 1], [23, 1], [121, 15], [101, 22], [105, 23], [106, 23], [108, 23], [155, 121], [120, 108], [19, 2], [25, 5], [33, 8], [35, 8], [28, 25], [29, 28]]
def get_levels():
   q, r, d = deque(sorted({(b, b) for a, b in list1 if all(k != b for k, _ in list1)})), [], defaultdict(list)
   while q:
      r.append(((n:=q.popleft())[0], [n[-1], *(l:=[a for a, b in list1 if b == n[-1]])]))
      q.extend([(n[0], i) for i in l])
   for a, b in r:
      if len(b) > 1:
         d[a].append(b)
   return [i for b in d.values() for i in ([b] if len(b) > 1 else b)]

print(get_levels())

输出:

[[[1, 15, 22, 23], [15, 121], [22, 101], [23, 105, 106, 108], [121, 155], [108, 120]], [2, 19], [[5, 25], [25, 28], [28, 29]], [8, 33, 35]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多