Предположим, что вы знаете, как создавать XML.
Давайте предположим, что «уровень» в ваших данных увеличивается, если данные вложены в предыдущий узел, и увеличивается только на 1. Если уровень уменьшается, это означает, что вы больше не говорите о текущем узле, а скорее о каком-то узле выше; уровень == 1 означает «прикрепить на уровне документа».
Для обработки увеличения уровней вам просто нужно отследить предыдущий узел. Если уровень увеличивается на единицу, вы создаете новый узел и делаете его дочерним по отношению к предыдущему узлу.
Чтобы обработать того же уровня , вам нужно запомнить родителя ранее созданного узла. Вы присоединяете новый узел к этому родительскому узлу, потому что это узел предыдущего узла.
Чтобы справиться с уменьшением уровней, вам необходимо отойти от предыдущего узла на несколько шагов, чтобы вы оказались на нужном уровне. Ты видишь узор?
На самом деле вам нужно запомнить всю цепочку от уровня документа до ранее созданного узла. Если next_node.level == previous_node.level + 1
, вы прикрепляете его к концу цепочки. В противном случае вы отступаете на previous_node.level - next_node.level + 1
пунктов вверх по цепочке и используете этот узел в качестве родителя. Мы предполагаем, что уровень 0 является уровнем документа.
Немного кода, чтобы проиллюстрировать это:
def nest(input):
ret = {'level': 0} # 'document level'
path = [ret]
for item in input:
node = dict(item) # a copy of item, lest we alter input
old_level = path[-1]['level'] # last element's
new_level = node['level']
delta = new_level - old_level - 1
if delta < 0:
path = path[:delta]
children_list = path[-1].get('_children', None) or []
children_list.append(node)
path[-1]['_children'] = children_list
path.append(node)
return ret
from pprint import PrettyPrinter
pr = PrettyPrint(indent=2).pprint
pr(nest(toc))
и вы видите
{ '_children': [ { '_children': [ { 'entryno': 2,
'level': 2,
'pageno': 19,
'title': 'title b'}],
'entryno': 1,
'level': 1,
'pageno': 17,
'title': 'title a'},
{ 'entryno': 3, 'level': 1, 'pageno': 25, 'title': 'title c'}],
'level': 0}
Под _children
мы перечисляем вложенные узлы.