Given an unsorted list with errors and skips, return a nested one. [{'level': 1}, {'level': 2}] => [{'level': 1, 'children': [{'level': 2, 'children': []}]}] A wrong list is also converted: [{'level': 2}, {'level': 1}] => [{'level': 2, 'children
(toc_list)
| 172 | |
| 173 | |
| 174 | def nest_toc_tokens(toc_list): |
| 175 | """Given an unsorted list with errors and skips, return a nested one. |
| 176 | |
| 177 | [{'level': 1}, {'level': 2}] |
| 178 | => |
| 179 | [{'level': 1, 'children': [{'level': 2, 'children': []}]}] |
| 180 | |
| 181 | A wrong list is also converted: |
| 182 | |
| 183 | [{'level': 2}, {'level': 1}] |
| 184 | => |
| 185 | [{'level': 2, 'children': []}, {'level': 1, 'children': []}] |
| 186 | """ |
| 187 | |
| 188 | ordered_list = [] |
| 189 | if len(toc_list): |
| 190 | # Initialize everything by processing the first entry |
| 191 | last = toc_list.pop(0) |
| 192 | last['children'] = [] |
| 193 | levels = [last['level']] |
| 194 | ordered_list.append(last) |
| 195 | parents = [] |
| 196 | |
| 197 | # Walk the rest nesting the entries properly |
| 198 | while toc_list: |
| 199 | t = toc_list.pop(0) |
| 200 | current_level = t['level'] |
| 201 | t['children'] = [] |
| 202 | |
| 203 | # Reduce depth if current level < last item's level |
| 204 | if current_level < levels[-1]: |
| 205 | # Pop last level since we know we are less than it |
| 206 | levels.pop() |
| 207 | |
| 208 | # Pop parents and levels we are less than or equal to |
| 209 | to_pop = 0 |
| 210 | for p in reversed(parents): |
| 211 | if current_level <= p['level']: |
| 212 | to_pop += 1 |
| 213 | else: # pragma: no cover |
| 214 | break |
| 215 | if to_pop: |
| 216 | levels = levels[:-to_pop] |
| 217 | parents = parents[:-to_pop] |
| 218 | |
| 219 | # Note current level as last |
| 220 | levels.append(current_level) |
| 221 | |
| 222 | # Level is the same, so append to |
| 223 | # the current parent (if available) |
| 224 | if current_level == levels[-1]: |
| 225 | (parents[-1]['children'] if parents |
| 226 | else ordered_list).append(t) |
| 227 | |
| 228 | # Current level is > last item's level, |
| 229 | # So make last item a parent and append current as child |
| 230 | else: |
| 231 | last['children'].append(t) |