@@ -27,60 +27,59 @@ def order_toc_list(toc_list):
27
27
[{'level': 1}, {'level': 2}]
28
28
=>
29
29
[{'level': 1, 'children': [{'level': 2, 'children': []}]}]
30
-
30
+
31
31
A wrong list is also converted:
32
32
[{'level': 2}, {'level': 1}]
33
33
=>
34
34
[{'level': 2, 'children': []}, {'level': 1, 'children': []}]
35
35
"""
36
-
37
- def build_correct (remaining_list , prev_elements = [{'level' : 1000 }]):
38
-
39
- if not remaining_list :
40
- return [], []
41
-
42
- current = remaining_list .pop (0 )
43
- if not 'children' in current .keys ():
44
- current ['children' ] = []
45
-
46
- if not prev_elements :
47
- # This happens for instance with [8, 1, 1], ie. when some
48
- # header level is outside a scope. We treat it as a
49
- # top-level
50
- next_elements , children = build_correct (remaining_list , [current ])
51
- current ['children' ].append (children )
52
- return [current ] + next_elements , []
53
-
54
- prev_element = prev_elements .pop ()
55
- children = []
56
- next_elements = []
57
- # Is current part of the child list or next list?
58
- if current ['level' ] > prev_element ['level' ]:
59
- #print "%d is a child of %d" % (current['level'], prev_element['level'])
60
- prev_elements .append (prev_element )
61
- prev_elements .append (current )
62
- prev_element ['children' ].append (current )
63
- next_elements2 , children2 = build_correct (remaining_list , prev_elements )
64
- children += children2
65
- next_elements += next_elements2
66
- else :
67
- #print "%d is ancestor of %d" % (current['level'], prev_element['level'])
68
- if not prev_elements :
69
- #print "No previous elements, so appending to the next set"
70
- next_elements .append (current )
71
- prev_elements = [current ]
72
- next_elements2 , children2 = build_correct (remaining_list , prev_elements )
73
- current ['children' ].extend (children2 )
36
+
37
+ ordered_list = []
38
+ if len (toc_list ):
39
+ # Initialize everything by processing the first entry
40
+ last = toc_list .pop (0 )
41
+ last ['children' ] = []
42
+ levels = [last ['level' ]]
43
+ ordered_list .append (last )
44
+ parents = []
45
+
46
+ # Walk the rest nesting the entries properly
47
+ while toc_list :
48
+ t = toc_list .pop (0 )
49
+ current_level = t ['level' ]
50
+ t ['children' ] = []
51
+
52
+ # Reduce depth if current level < last item's level
53
+ if current_level < levels [- 1 ]:
54
+ # Pop last level since we know we are less than it
55
+ levels .pop ()
56
+
57
+ # Pop parents and levels we are less than or equal to
58
+ to_pop = 0
59
+ for p in reversed (parents ):
60
+ if current_level <= p ['level' ]:
61
+ to_pop += 1
62
+ else :
63
+ break
64
+ if to_pop :
65
+ levels = levels [:- to_pop ]
66
+ parents = parents [:- to_pop ]
67
+
68
+ # Note current level as last
69
+ levels .append (current_level )
70
+
71
+ # Level is the same, so append to the current parent (if available)
72
+ if current_level == levels [- 1 ]:
73
+ (parents [- 1 ]['children' ] if parents else ordered_list ).append (t )
74
+
75
+ # Current level is > last item's level,
76
+ # So make last item a parent and append current as child
74
77
else :
75
- #print "Previous elements, comparing to those first"
76
- remaining_list .insert (0 , current )
77
- next_elements2 , children2 = build_correct (remaining_list , prev_elements )
78
- children .extend (children2 )
79
- next_elements += next_elements2
80
-
81
- return next_elements , children
82
-
83
- ordered_list , __ = build_correct (toc_list )
78
+ last ['children' ].append (t )
79
+ parents .append (last )
80
+ levels .append (current_level )
81
+ last = t
82
+
84
83
return ordered_list
85
84
86
85
0 commit comments