The objective is to create a function with the signature
declare function addChild(nodes: Node[], parentId: number, newNode: Node): void;
. This function will add the
newNode
to the
children
property of the node in the
nodes
tree that has an
id
matching the provided
parentId
. Here are some assumptions:
- You aim to modify existing trees instead of making copies.
- In case multiple nodes share the target id, adding the new node to the children of any one of them is acceptable (preferably the first encountered during tree traversal).
- If no node in the tree matches the target id, leaving the tree unchanged is acceptable.
One possible approach to achieve this is through the following code snippet:
function addChild(nodes: Node[], parentId: number, newNode: Node): boolean {
for (const node of nodes) {
if (node.id === parentId) {
(node.children ??= []).push(newNode);
return true;
}
if (node.children) {
const found = addChild(node.children, parentId, newNode);
if (found) return true;
}
}
return false;
}
This function utilizes recursion, which is a straightforward way to handle recursive data structures. By returning a boolean
, it can signal whether the target node was found or not, allowing for early termination of tree traversal upon success.
For each node in the array supplied as input, we check its id against the specified parent id. If they match, we have located the node and proceed to add the new node to its children. Since the children property is optional, we may need to initialize it as an empty array before appending the new node. This initialization step can be streamlined using nullish coalescing assignment (??=
) in the form:
(node.children ??= []).push(newNode);
If the current node is not the target node, the function recursively calls itself on the node's children array. If any of these recursive calls finds the target node, the search terminates early by returning true
. Otherwise, the process continues until completion.
If the target node remains elusive after traversing the complete tree, the function returns false
. While this outcome is not intended for user-invoked calls, it is expected within many subtrees of the original structure.
Let's put the function to the test:
addChild(NODE_DATA, 4, { id: 7, name: "G" });
console.log(JSON.stringify(NODE_DATA))
// Expected output:
// [{"id":1,"name":"A"},{"id":2,"name":"B","children":[{"id":3,"name":"C"},
// {"id":4,"name":"D","children":[{"id":7,"name":"G"}]},
// {"id":5,"name":"E","children":[{"id":6,"name":"F"}]}]}]
The test appears successful.
Playground link to code