如何在Python中从字典中打印树

发布于 2025-01-18 18:04:29 字数 1157 浏览 0 评论 0原文

我正在尝试在 python 中实现 ldd 。但是,我正在努力将数据表示为类似树的结构。 Linux库取决于其他一些库,因此我的任务是跟踪依赖项列表,直到找不到依赖关系为止。 我在下面显示的字典中有数据,

{lib_A: [lib_1, lib_2, lib_3, lib_4], lib_1: [lib_x, lib_y, lib_z], lib_x: [lib_i], lib_y: [lib_p], lib_2: [lib_a, lib_b], lib_a: [lib_11]......}

其中 lib_1 lib_2 lib_3 lib_4 取决于 lib_a 。然后 lib_x lib_y lib_z 取决于 lib_1 等。列表一直持续到找不到依赖性为止。如果我将数据打印在循环中,则输出看起来如下所示,

for lib, dep_lib in dependency_dict.items():
    print(lib, dep_lib)
lib_A [lib_1, lib_2, lib_3, lib_4]
lib_1 [lib_x, lib_y, lib_z]
lib_x [lib_i]
lib_y [lib_p]
lib_2 [lib_a, lib_b]
lib_a [lib_11]
...
..

我想将上述数据表示为像树的结构一样,如下所示。

lib_A <= lib_1
         <= lib_x
            <= lib_i
         <= lib_y
            <= lib_p
         <= lib_z
      <= lib_2
         <= lib_a
            <= lib_11
         <= lib_b
      <= lib_3
      <= lib_4


I am trying to implement ldd kind of application in python. However, I am struggling to represent the data as a tree like structure. The linux libraries are dependent on some other libraries, so my task is to track the dependency list until no dependency is found.
I have data in dictionary shown below,

{lib_A: [lib_1, lib_2, lib_3, lib_4], lib_1: [lib_x, lib_y, lib_z], lib_x: [lib_i], lib_y: [lib_p], lib_2: [lib_a, lib_b], lib_a: [lib_11]......}

where lib_1, lib_2, lib_3, and lib_4 depends on lib_A. Then lib_x, lib_y, and lib_z depends on lib_1 and so on. The list continues until no dependency is found. If I print the data in a for loop the output looks like this as shown below,

for lib, dep_lib in dependency_dict.items():
    print(lib, dep_lib)
lib_A [lib_1, lib_2, lib_3, lib_4]
lib_1 [lib_x, lib_y, lib_z]
lib_x [lib_i]
lib_y [lib_p]
lib_2 [lib_a, lib_b]
lib_a [lib_11]
...
..

and I want to represent the above data as a tree like structure as shown below.

lib_A <= lib_1
         <= lib_x
            <= lib_i
         <= lib_y
            <= lib_p
         <= lib_z
      <= lib_2
         <= lib_a
            <= lib_11
         <= lib_b
      <= lib_3
      <= lib_4


如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

┼── 2025-01-25 18:04:29

当处理基于树的结构时,通常很自然地使用递归函数来处理它。为了产生您想要的输出,我会写这样的内容:

def process_lib(data, lib, padding=0):
    if padding == 0:
        print(lib)
    else:
        print(" "*padding, "<=", lib)

    for child in data.get(lib, []): # base case: lib is not in the dict
        process_lib(data, child, padding + 3)  # recursive case

这并不完全复制示例的第一行,因为我们将 lib_Alib_1 放在自己的行上代码> 在下一行。您可以为 padding == 0 情况添加更多特殊情况逻辑,并弄清楚如何使第一个子项直接跟随它,但希望这个输出足够好:

lib_A
    <= lib_1
       <= lib_x
          <= lib_i
       <= lib_y
          <= lib_p
       <= lib_z
    <= lib_2
       <= lib_a
          <= lib_11
       <= lib_b
    <= lib_3
    <= lib_4

此代码可能仅适用于简单的树。如果您的真实数据是一个更复杂的图表,并且在依赖关系层次结构中的多个点上显示相同的库,那么您需要更复杂的东西。您需要跟踪已经看到的节点,并且要么根本不再打印它们,要么打印它们但不打印它们的依赖项。这是执行后者的实现:

def process_lib(data, lib, padding=0, seen=None):
    if seen is None:
        seen = set()
    if padding == 0:
        print(lib)
    else:
        print(" "*padding, "<=", lib)

    if lib in seen:
        print(" "*(padding+3), "<= ...") # alternate base case
    else:
        seen.add(lib)
        for child in data.get(lib, []):
            process_lib(data, child, padding + 3, seen)

如果您根本不想重复,请使用:

def process_lib(data, lib, padding=0, seen=None):
    if seen is None:
        seen = set()
    if padding == 0:
        print(lib)
    else:
        print(" "*padding, "<=", lib)

    seen.add(lib)
    for child in data.get(lib, []):
        if child not in seen:
            process_lib(data, child, padding + 3, seen)

When dealing with a tree based structure, it's often natural to use a recursive function to process it. To produce the output you want, I'd write something like this:

def process_lib(data, lib, padding=0):
    if padding == 0:
        print(lib)
    else:
        print(" "*padding, "<=", lib)

    for child in data.get(lib, []): # base case: lib is not in the dict
        process_lib(data, child, padding + 3)  # recursive case

This doesn't exactly replicate the first line of your example, since we put lib_A on its own line with lib_1 on the next line. You could put in more special case logic for the padding == 0 case and figure out how to make the first child directly follow it, but hopefully this output is good enough:

lib_A
    <= lib_1
       <= lib_x
          <= lib_i
       <= lib_y
          <= lib_p
       <= lib_z
    <= lib_2
       <= lib_a
          <= lib_11
       <= lib_b
    <= lib_3
    <= lib_4

This code probably only works properly for simple trees. If your real data is a more complicated graph with the same libraries showing up at multiple points in the dependency hierarchy, then you need something a little more complicated. You need to keep track of which nodes have already been seen, and either not print them out again at all, or print them but not their dependencies. Here's an implementation that does the latter:

def process_lib(data, lib, padding=0, seen=None):
    if seen is None:
        seen = set()
    if padding == 0:
        print(lib)
    else:
        print(" "*padding, "<=", lib)

    if lib in seen:
        print(" "*(padding+3), "<= ...") # alternate base case
    else:
        seen.add(lib)
        for child in data.get(lib, []):
            process_lib(data, child, padding + 3, seen)

If you don't want duplicates at all, use this:

def process_lib(data, lib, padding=0, seen=None):
    if seen is None:
        seen = set()
    if padding == 0:
        print(lib)
    else:
        print(" "*padding, "<=", lib)

    seen.add(lib)
    for child in data.get(lib, []):
        if child not in seen:
            process_lib(data, child, padding + 3, seen)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文