← Back to table of contents

Component Tree Search

Flatten with accumulator, then filter

TimeO(2n)SpaceO(n)Suboptimal
Two passes: O(n) to flatten, then O(n) to filter. A single-pass approach only collects matching nodes as it descends, avoiding the extra traversal and the full intermediate list.

Code

1interface ComponentNode {
2    id: string
3    type: string
4    children?: ComponentNode[]
5}
6
7const tree: ComponentNode = {
8    id: "root",
9    type: "Page",
10    children: [
11        {
12            id: "header",
13            type: "Header",
14            children: [
15                { id: "logo", type: "Image" },
16                { id: "nav", type: "Nav" }
17            ]
18        },
19        {
20            id: "content",
21            type: "Section",
22            children: [
23                { id: "hero", type: "Image" },
24                { id: "cta", type: "Button" }
25            ]
26        }
27    ]
28}
29
30function flatten(tree: ComponentNode): ComponentNode[] {
31    const result: ComponentNode[] = [tree]
32
33    if (tree.children) {
34        for (const child of tree.children) {
35            result.push(...flatten(child))
36        }
37    }
38
39    return result
40}
41
42
43function findComponentsByType(
44    tree: ComponentNode,
45    targetType: string
46): ComponentNode[] {
47    return flatten(tree).filter(node => node.type === targetType)
48}
49
50console.log(findComponentsByType(tree, "Button"))
51

Animation

Component tree
Pageroot
Headerheader
Imagelogo
Navnav
Sectioncontent
Imagehero
Buttoncta
Result (traversal order)
Speed: