有谁知道任何 Python 库可以让您简单快速地为其提供嵌套到任意级别的对象,例如按照您在此 gist中找到的内容的 dict 树,它可以吐出一个可行的树图形文件?
在这里,简单是关键,因为我必须能够与没有技术头脑的人一起工作。
我所说的“图树”是指以下内容,我可以向它提供一个嵌套的值字典,然后它会创建树结构:
(来源:rubyforge.org)
有谁知道任何 Python 库可以让您简单快速地为其提供嵌套到任意级别的对象,例如按照您在此 gist中找到的内容的 dict 树,它可以吐出一个可行的树图形文件?
在这里,简单是关键,因为我必须能够与没有技术头脑的人一起工作。
我所说的“图树”是指以下内容,我可以向它提供一个嵌套的值字典,然后它会创建树结构:
(来源:rubyforge.org)
我不确定这是否完全符合您的想法,但这是您首先想到的。
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 可以读取的文件。
所以我在这个答案中为我的代码片段推荐和使用的库不是python 库,但它是一个 python 友好的库,我的意思是使用这个库的代码可以插入到 python 模块中来处理数据和这个外部代码将连接到两端现存的python代码,即输入和输出,我怀疑,虽然我当然不知道,但这就是“python库”标准的真正含义。因此,如果您正在编写 Web 应用程序,则此代码将是客户端的。换句话说,这个库不是 python,但它可以与 python 一起使用。
它的输入(几乎)是原始 python dicts,更具体地说,json.load(a_python_dict)返回一个 json 数组或对象,这个 javascript 库当然可以识别的格式;和
输出格式是 HTML 或 SVG,而不是某些特定语言格式的对象
var tree = d3.layout.tree().size([h, w]);
在d3的示例文件夹中还有几个树的示例(工作代码),您可以从我上面提供的链接克隆/下载它们。
因为d3是一个javascript库,它的原生数据格式是JSON。
基本结构是一个嵌套字典,每个字典代表一个具有两个值的单个节点,节点的名称及其子节点(存储在一个数组中),分别以names和children为键:
{"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字典表示,我如上所述将其转换为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 在浏览器中呈现;上图只是我的浏览器窗口的屏幕截图。
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(带有id
和children
字段)的示例。
Graph也可以通过递归迭代创建,以及多种格式的读写: https ://networkx.github.io/documentation/stable/reference/readwrite/index.html
我一直在寻找类似的问题:使用嵌套字典打印字典的键,其中键结构非常周期性。因此,我编写了一个递归函数,它打印每个 dict 和嵌套 dicts 的键,但只针对单个分支。
希望以下代码片段对其他人有所帮助:
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 | | |
根据您的需要,但如果您只需要它来轻松查看内容,您可以使用在线工具 - “Python dict formatter and viewer”可以将 dict 呈现为树。