tree representation of Python data
Thomas Passin
list1 at tompassin.net
Sun Jan 22 12:11:20 EST 2023
On 1/21/2023 10:03 AM, Dino wrote:
>
> I have a question that is a bit of a shot in the dark. I have this nice
> bash utility installed:
>
> $ tree -d unit/
> unit/
> ├── mocks
> ├── plugins
> │ ├── ast
> │ ├── editor
> │ ├── editor-autosuggest
> │ ├── editor-metadata
> │ ├── json-schema-validator
> │ │ └── test-documents
> │ └── validate-semantic
> │ ├── 2and3
> │ ├── bugs
> │ └── oas3
> └── standalone
> └── topbar-insert
>
> I just thought that it would be great if there was a Python utility that
> visualized a similar graph for nested data structures.
> Of course I am aware of indent (json.dumps()) and pprint, and they are
> OK options for my need. It's just that the compact, improved
> visualization would be nice to have. Not so nice that I would go out of
> my way to build, but nice enough to use an exising package.
It's not clear to me whether you want to display JSON structures or
Python objects. However, Python dictionaries are so similar to JSON
structures that a dictionary example should be pretty close.
This can actually be a tricky problem because for complicated nesting,
it's not that easy to work out how to display the elements. The
examples posted in this thread so far have been somewhat obscured by the
use of leader lines, etc, so that it's a little hard to discern the
simple core of the algorithm.
Below I include code that displays each leaf element on its own indented
line, can only display keys and simple leaf values, and does not
construct leader lines so as to keep the code easy to read. In this
form it can only display Python dictionaries but could be modified for
JSON without too much work.
"""Display nested objects as an indented list."""
INDENT = ' ' * 3
DICT = {'a': {'aa':'AA', 'ab':'AB'},
'b': {'ba': {'baa': 'BAA', 'bab': 'BAB'},
'bb':'BB'},
'c': ['CA', 'CB'],
'd': 'D' }
SIMPLE_TYPES = (int, float, str, bytes)
def unroll(obj, indent = ''):
if isinstance(obj, dict):
unroll_dict(obj, indent)
else:
"""unroll other kinds of objects (not implemented)."""
print(indent, 'Can only unroll nested dictionaries')
def unroll_dict(dct, indent = ''):
"""Unroll a dictionary whose values can be either simple or
nested.
"""
for k, v in dct.items():
g.es(indent, k)
new_indent = indent + INDENT
if type(v) in SIMPLE_TYPES:
print(new_indent, v)
else:
unroll(v, new_indent)
# print(f'{new_indent}{v}')
unroll(DICT)
Output:
a
aa
AA
ab
AB
b
ba
baa
BAA
bab
BAB
bb
BB
c
Can only unroll nested dictionaries
d
D
If you change the last else block, you can make use of the object's
internal representation (not for JSON, of course). Change the block to
read:
# unroll(v, new_indent)
print(f'{new_indent}{v}')
This change gives the following output:
a
{'aa': 'AA', 'ab': 'AB'}
b
{'ba': {'baa': 'BAA', 'bab': 'BAB'}, 'bb': 'BB'}
c
['CA', 'CB']
d
D
In practice, I would collect the text fragments into a list instead of
printing them, then print the joined list at the end.
More information about the Python-list
mailing list