修改 正如@Alfe在评论中建议的那样,在这种情况下的确切问题是以下代码无法处理具有相同值的节点。那么,如何在不改变节点值的情况下获得预期的输出?
我正在执行以下代码,以便从JSON数据生成树:
from __future__ import print_function
import json
import sys
# Tree in JSON format
s = '{"Harry": {"children": ["Bill", {"Jane": {"children": [{"Diane": {"children": ["Mary"]}}, "Mark"]}}]}}'
# Convert JSON tree to a Python dict
data = json.loads(s)
# Extract tree edges from the dict
edges = []
def get_edges(treedict, parent=None):
name = next(iter(treedict.keys()))
if parent is not None:
edges.append((parent, name))
for item in treedict[name]["children"]:
if isinstance(item, dict):
get_edges(item, parent=name)
else:
edges.append((name, item))
get_edges(data)
# Dump edge list in Graphviz DOT format
print('strict digraph tree {')
for row in edges:
print(' {0} -> {1};'.format(*row))
print('}')
终端使用的命令:python filename.py | dot -Tpng -otree.png
但是如果我用整数输入JSON数据:
s = '{"92": {"children": [{"87": {"children": [87, 96]}}, {"96": {"children": [90, 105]}}]}}'
我得到以下输出:(这是错误的!)
我在这里做错了什么?如何解决这个问题?
答案 0 :(得分:2)
根据问题中的编辑进行编辑:
考虑到你的输出,它给了我:
92 -> 87;
87 -> 87;
87 -> 96;
92 -> 96;
96 -> 90;
96 -> 105;
它显示"87"
和87
相同,因为您使用.format()
print
将{值}插入字符串中而不依赖于维护引号"
。例如:
>>> '{}'.format(1)
'1'
>>> '{}'.format('1')
'1'
为了解决这个问题,你可以这样做:
for parent, child in edges:
parent = '"{}"'.format(parent) if isinstance(parent, str) else parent
child = '"{}"'.format(child) if isinstance(child, str) else child
print(' {0} -> {1};'.format(parent, child))
打印:
"92" -> "87";
"87" -> 87;
"87" -> 96;
"92" -> "96";
"96" -> 90;
"96" -> 105;
答案 1 :(得分:1)
你的问题是使用统一字符串和数字的工具dot
,因此它将名称相同的节点视为相同(意思是:只是一个)。您需要为每个节点提供唯一的ID。然后可以调整图形输出以反映不同节点中的相同名称。
示例:
echo '
strict digraph tree {
92 -> 87 -> "87a";
"87a" [label="87"];
87 -> "96a";
"96a" [label="96"];
92 -> 96 -> 90;
96 -> 105 }
' | dot -Tpng -otree.png
这将产生您想要的输出(带有有向边)。
我相应地更改了您的代码以实现此调整:
#!/usr/bin/env python2
from __future__ import print_function
import json
import sys
# Tree in JSON format
s = '{"92": {"children": [{"87": {"children": [87, 96]}}, {"96": {"children": [90, 105]}}]}}'
# Convert JSON tree to a Python dict
data = json.loads(s)
# Extract tree edges from the dict
edges = []
def x(node):
return '%s%s' % (node, type(node))
def get_edges(treedict, parent=None):
name = next(iter(treedict.keys()))
if parent is not None:
edges.append((x(parent), x(name), parent, name))
for item in treedict[name]["children"]:
if isinstance(item, dict):
get_edges(item, parent=name)
else:
edges.append((x(name), x(item), name, item))
get_edges(data)
# Dump edge list in Graphviz DOT format
print('strict digraph tree {')
for row in edges:
print(' "{0}" -> "{1}"; "{0}" [label="{2}"]; "{1}" [label="{3}"];'.format(*row))
print('}')
这使用特殊的内部节点ID,它们组合了节点名称及其类型(str / unicode或int),并为每个隐藏此内部ID的节点设置标签。