【问题标题】:Python library for creating tree graphs out of nested Python objects (dicts)用于从嵌套的 Python 对象 (dicts) 创建树形图的 Python 库
【发布时间】:2013-01-25 17:18:59
【问题描述】:

有没有人知道任何 Python 库可以让你简单快速地为它提供一个嵌套到任意级别的对象,例如一个字典树,就像你在 this gist 中找到的那样,它可以吐出出一个可行的树图文件?

在这里,简单是关键,因为我必须能够与没有技术头脑的人一起工作。

我所说的“图树”是指以下内容,我可以为它提供一个嵌套的值字典,然后它会创建树结构:


(来源:rubyforge.org

【问题讨论】:

标签: python graph dictionary tree


【解决方案1】:

我不确定这是否是您的想法,但这是您首先想到的。

blockdiag 主要用作类似于Graphviz 的独立文件处理器(存在Python 接口)。它接受一个文本文件作为输入,语法非常简单,并生成图像作为输出。

您应该能够编写一个简单的 shim 来输出您的递归 dict 结构,该结构已格式化为独立 blockdiag 脚本的输入,或者导入 blockdiag 包的必要内部结构并直接驱动输出。

如果这听起来很有希望,我会看看是否可以编写一些示例代码。

编辑示例代码:

def print_blockdiag(tree, parent=None):
    if not parent: print('blockdiag { orientation = portrait')
    for key in tree:
        if parent: print('   {} -> {};'.format(parent, key))
        print_blockdiag(tree[key], key)
    if not parent: print('}')

这将输出一个blockdiag可以读取的文件。

【讨论】:

    【解决方案2】:

    所以我在这个答案中为我的代码 sn-p 推荐和使用的库 不是 python 库,但它是一个 python 友好的库,我的意思是使用这个库的代码可以插入到 python 模块中来处理数据,这个 foreign 代码将连接到两端现存的 python 代码,即输入和输出,我怀疑,虽然我当然不知道,这就是“python 库”标准的真正含义。因此,如果您正在编写 Web 应用程序,则此代码将是客户端的。换句话说,这个库不是python,但它可以与python一起使用。

    1. 它的输入是(几乎)原始的 python dicts,更具体地说,json.load(a_python_dict) 返回一个 json 数组或对象,这种格式javascript库当然可以识别;和

    2. 输出格式是 HTML 或 SVG,而不是某些对象 特定语言格式

    您可以使用d3.js。它有一个class 专门用于渲染树:

    var tree = d3.layout.tree().size([h, w]);
    

    d3 源的 example 文件夹 中还有几个树的示例(工作代码),您可以从我提供的链接中克隆/下载它们以上。

    因为d3是一个javascript库,它的原生数据格式是JSON

    基本结构是一个嵌套字典,每个字典代表一个具有两个值的单个节点,节点的名称及其子节点(存储在一个数组中),键为 names儿童

    {"name": "a_root_node", "children": ["B", "C"]}
    

    当然,在 python 字典和 JSON 之间转换也很简单:

    >>> d = {"name": 'A', "children": ['B', 'C']}
    >>> import json as JSON
    >>> dj = JSON.dumps(d)
    >>> dj
        '{"name": "A", "children": ["B", "C"]}'
    

    这是一个较大的树(十几个节点)的python dictionary 表示,我如上所述将其转换为 json,然后在 d3 中呈现为所示的树在下图中:

    tree = {'name': 'root', 'children': [{'name': 'node 2', 'children': 
           [{'name': 'node 4', 'children': [{'name': 'node 10', 'size': 7500}, 
           {'name': 'node 11', 'size': 12000}]}, {'name': 'node 5', 'children': 
           [{'name': 'node 12', 'children': [{'name': 'node 16', 'size': 10000}, 
           {'name': 'node 17', 'size': 12000}]}, {'name': 'node 13', 'size': 5000}]}]}, 
           {'name': 'node 3', 'children': [{'name': 'node 6', 'children': 
           [{'name': 'node 14', 'size': 8000}, {'name': 'node 15', 'size': 9000}]}, 
           {'name': 'node 7', 'children': [{'name': 'node 8', 'size': 10000}, 
           {'name': 'node 9', 'size': 12000}]}]}]}
    

    注意:d3在浏览器中渲染;上图只是我的浏览器窗口的屏幕截图。

    【讨论】:

    • -1:D3 非常棒,但它是一个 Javascript 工具,而不是 Python。如果您正在编写 Python 代码,它并没有真正的帮助。
    • 喜欢这个答案。最后,我有一种简洁的方式来显示 python 脚本的输出!
    【解决方案3】:

    D3.js 是一个主要用于可视化的库...

    据我所知,它没有提供用于遍历图形和对其进行数学运算的便捷工具。 但它们在 Python networkX 包中:

    import networkx as nx
    
    graph_data = {
        'id': 'root',
        'children': [
            {
                'id': 'A',
                'children': [
                    {
                        'id': 'B', 'children': [{'id': 'B1'}, {'id': 'B2'}]
                    },
                    {
                        'id': 'C'
                    }
                ]
            }
        ]
    }
    
    G = nx.readwrite.json_graph.tree_graph(graph_data)
    
    print('EDGES: ', G.edges())
    # EDGES: [('root', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B1'), ('B', 'B2')]
    print('NODES: ', G.nodes())
    # NODES: ['root', 'A', 'B', 'B1', 'B2', 'C']
    

    这是一个从结构创建相同 D3.js 的示例(带有 idchildren 字段)。

    图形也可以通过递归迭代创建,以及以多种格式读写: https://networkx.github.io/documentation/stable/reference/readwrite/index.html

    【讨论】:

      【解决方案4】:

      我一直在寻找类似的问题:使用嵌套字典打印字典的键,其中键结构非常周期性。 因此,我编写了一个递归函数,用于打印每个字典和嵌套字典的键,用于单个分支

      希望以下代码 sn-p 对其他人有所帮助:

      from itertools import zip_longest
      
      def dictPrintKeysTopBranch(dic):
          #track recursive depth
          depth=dictPrintKeysTopBranch.data.get('depth',-1)+1;
          dictPrintKeysTopBranch.data['depth']=depth;
      
          #accumalte keys from nested dicts
          if type(dic) is type(dict()):
              listKeys=sorted(list(dic.keys()));
      
              #save keys of current depth
              dictPrintKeysTopBranch.data['listKeysDepth{}'.format(depth)]=listKeys;
      
              #repeat for top branch
              dictPrintKeysTopBranch(dic[listKeys[0]]);
      
          #print accumalated list of keys
          else: 
              #pad lists 
              lists=[];
              maxlen=[];
              for d in range(depth):
                  l=dictPrintKeysTopBranch.data['listKeysDepth{}'.format(d)];
                  lists.append(l);
      
                  lens = [len(s) for s in l];
                  maxlen.append(max(lens)+1);
      
              i=-1;
              for zipped in zip_longest(*lists, fillvalue=' '):
                  i=i+1;
                  #print(x)
                  row = '';
                  j=-1;
                  for z in zipped:
                      j=j+1;
                      if i==0:
                          row = row+ ((' {: <'+str(maxlen[j])+'} -->\\').format(z));
                      else :
                          row = row+ ((' {: <'+str(maxlen[j])+'}    |').format(z));
                  print(row.strip('\\|->'));
      
          dictPrintKeysTopBranch.data={};
      dictPrintKeysTopBranch.data={};
      

      这里是一个例子:

      mydict = { 'topLv':{'secLv':{'thirdLv':{'item1':42,'item2':'foo'}}}, 
                 'topLvItem':[1,2,3], 
                 'topLvOther':{'notPrinted':':('}
               }
      dictPrintKeysTopBranch(mydict)
      

      输出:

      topLv       -->\ secLv  -->\ thirdLv  -->\ item1  
      topLvItem      |           |             | item2     
      topLvOther     |           |             |         
      

      【讨论】:

        【解决方案5】:

        根据您的需要,但如果您只需要它来轻松查看内容,您可以使用在线工具 - "Python dict formatter and viewer" 可以将 dict 呈现为树。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-02-16
          • 2019-01-04
          • 2016-12-07
          • 2020-08-26
          • 2011-01-27
          • 1970-01-01
          • 2019-11-23
          相关资源
          最近更新 更多