Convert Leveled Rich-Text Tokens into Nested Lists
FigmaSoftware Engineer · OnsiteLast updated
Tests parsing a linear sequence of leveled tokens into a hierarchical tree or nested list structure using stack-based tree construction.
Problem Statement
In rich-text editors like Figma, hierarchical bulleted and numbered lists are often stored as a flat stream of tokens, where each token has a display string and a nesting level (an integer starting at 1).
Write a function build_nested_list(tokens) that converts an ordered sequence of leveled tokens into a list of nested nodes representing the document structure.
Each node in the output should be an instance of ListItem:
class ListItem:
def __init__(self, text: str):
self.text = text
self.children = [] # List of ListItem objects
Nesting Rules
- Tokens with
level == 1are top-level items and must be added directly to the root output list. - A token with
level > 1is placed as a child of the most recent preceding token whose level is strictly less than its own (parent_level < current_level). - If multiple preceding items have levels smaller than the current token's level, it attaches to the deepest (most recent) such item.
- If a token's level is greater than
1but no preceding item has a smaller level (for example, the list starts at level2), treat it as a root-level item. - Original token order must be preserved.
Function Signature
def build_nested_list(tokens: list[tuple[int, str]]) -> list[ListItem]:
pass
Examples
Example 1
Input:
tokens = [
(1, "Fruit"),
(2, "Apple"),
(2, "Banana"),
(3, "Cavendish"),
(1, "Vegetable")
]
Output:
A list with two top-level ListItem objects:
"Fruit"children:"Apple","Banana""Banana"has child"Cavendish"
"Vegetable"children:[]
Example 2 (Multi-level jump)
Input:
tokens = [
(1, "Title"),
(3, "Deep note"),
(2, "Section")
]
Output:
"Title"has child"Deep note"(because"Title"is the closest ancestor withlevel < 3)."Section"is also a direct child of"Title"(since its level2drops back below"Deep note"'s level3but is greater than1).
Constraints
0 <= len(tokens) <= 10^51 <= level <= 10^4textis a non-empty string with length up to100.- Expected time complexity:
O(N)whereNis the number of tokens. - Expected auxiliary space complexity:
O(N).
Hints
Hint 1
A stack of active ancestor nodes alongside their respective levels helps track where the next token belongs.
Hint 2
When encountering a token with level L, pop elements from the stack until the top element has a level strictly less than L.
Hint 3
If the stack becomes empty after popping, the current token is a root item; otherwise, append it to the children of the item at the top of the stack, and then push the current token onto the stack.
Follow-up questions
- How would you serialize this nested structure back into the original flat sequence of leveled tokens?
- If the product requirement changes such that a jump from level 1 to level 3 must synthesize empty placeholder nodes at level 2, how would you update your logic?
- How would you handle streaming tokens where nodes can be asynchronously edited or shifted in depth in real-time?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.