从对象列表构建树

Build a tree from a list of objects

我正在尝试从对象列表构建一棵树,这些对象具有多个属性。 每个对象可以有3个属性,它们在构建树中起作用,即velocity altitude exposure.

#Data structure

class Test():
   pass

tests = []
for el in data:
   test = Test()
   test.velocity = el[0] #100km/h or 120km/h or 140km/h
   test.altitude = el[1] #20m or 40m or 60m
   test.exposure = el[2] #10uSv or 20uSv or 30uSv
   #more data is assigned which is not shown as irrelevant
   tests.append(test)

# I am trying to build a data tree like the one below.
# Obviously it would be different than this one and depend on actual data input.
# Example built statically using anytree

Tests
├── 100km/h
│   ├── 20m
│   │   └── 10uSv
│   ├── 40m
│   │   └── 10uSv
│   └── 60m
│       └── 20uSv
├── 120km/h
│   ├── 40m
│   │   ├── 20uSv
│   │   └── 30uSv
│   └── 60m
│       ├── 20uSv
│       └── 30uSv
└── 140km/h
    └── 20m
        └── 30uSv

虽然这个问题看起来很简单(可能不是)我就是想不通。

干杯!

你没有提供原始数据,所以我试着猜一下。

我从构建嵌套的字典开始,然后使用递归函数将它们转换为 anytree 格式。

代码如下:

import itertools

import anytree

data = [
    ['100km/h', '20m', '10uSv'],
    ['100km/h', '40m', '10uSv'],
    ['100km/h', '60m', '20uSv'],
    ['120km/h', '40m', '20uSv'],
    ['120km/h', '40m', '30uSv'],
    ['120km/h', '60m', '20uSv'],
    ['120km/h', '60m', '30uSv'],
    ['140km/h', '20m', '30uSv'],
]

# Construct nested dicts
res = {'Tests': {}}

for a, b, c in data:
    res['Tests'].setdefault(a, {}).setdefault(b, {}).setdefault(c, True)

__import__('pprint').pprint(res)
# {'Tests': {'100km/h': {'20m': {'10uSv': True},
#                        '40m': {'10uSv': True},
#                        '60m': {'20uSv': True}},
#            '120km/h': {'40m': {'20uSv': True, '30uSv': True},
#                        '60m': {'20uSv': True, '30uSv': True}},
#            '140km/h': {'20m': {'30uSv': True}}}}


# Convert nested dicts to anytree format
def dict_to_tree(d, parent=None):
    if isinstance(d, bool):
        return

    for key in d:
        node = anytree.Node(key, parent)
        dict_to_tree(d[key], node)

root = anytree.Node('Tests')
dict_to_tree(res['Tests'], root)

for pre, fill, node in anytree.RenderTree(root):
    print(f'{pre}{node.name}')
# Tests
# ├── 100km/h
# │   ├── 20m
# │   │   └── 10uSv
# │   ├── 40m
# │   │   └── 10uSv
# │   └── 60m
# │       └── 20uSv
# ├── 120km/h
# │   ├── 40m
# │   │   ├── 20uSv
# │   │   └── 30uSv
# │   └── 60m
# │       ├── 20uSv
# │       └── 30uSv
# └── 140km/h
#     └── 20m
#         └── 30uSv