0

I have and object literal that is essentially a tree that does not have a fixed number of levels. How can I go about searching the tree for a particualy node and then return that node when found in an effcient manner in javascript?

Essentially I have a tree like this and would like to find the node with the title 'randomNode_1' and get back data[0].children[0].children[0] or for a individual search get back .children[0].children[0] or just a simple way of replacing the object found during the search.

var data = [
{
title: 'topNode',
 children: [
   {
       title: 'node1',
       children: [
       {
           title: 'randomNode_1'
       },
       {   
           title: 'node2',
           children: [
           {
               title: 'randomNode_2',
               children:[
               {   
                   title: 'node2',
                   children: [
                   {
                       title: 'randomNode_3',
                   }]
               }
               ]
           }]
       }]
   }
  ]
 }];
  • You need to explain more thoroughly what you are trying to do. It might make sense to you, but your **"OR CASES"** don't make sense to the rest of the world. Try to focus on each one, while maintaining brevity. Technical writing, which is what your doing, takes practice. For more help refer to https://stackoverflow.com/help/how-to-ask – JΛYDΞV Jun 28 '21 at 03:28

1 Answers1

1

You can use a recursive generator function...

This example is simple but robust:

var data = [{ title: 'topNode', children: [{ title: 'node1', children: [{ title: 'randomNode_1' }, { title: 'node2', children: [{ title: 'randomNode_2', children: [{ title: 'node2', children: [{ title: 'randomNode_3', }] }] }] }] }] }];

function* findAllNode(child, title) {
    for (const node of child) {
        if (node.title === title)
            yield node;
        if (node.children)
            yield* findAllNode(node.children, title);
    }
}
for (const node of findAllNode(data, "randomNode_1")) {
    node.msg = "Hello, World"; // Modify node
    break; // Get Only first matched node;
}
// Return All Node 
console.log([...findAllNode(data, "randomNode_1")])

This is modified one that also support node index (keys):

var data = [{ title: 'topNode', children: [{ title: 'node1', children: [{ title: 'randomNode_1' }, { title: 'node2', children: [{ title: 'randomNode_2', children: [{ title: 'node2', children: [{ title: 'randomNode_3', }] }] }] }] }] }];

let findByIndex = (data, keys) => keys.reduce((o, k) => o[k], data);

function* findAllNode(child, title) {
    for (let i = 0; i < child.length; i++) {
        const node = child[i];
        if (node.title === title)
            yield [node, [i]];
        if (node.children) for (const unit of findAllNode(node.children, title)) {
            unit[1].unshift(i, "children");
            yield unit
        }
    }
}
for (const [node, index] of findAllNode(data, "randomNode_1")) {
    console.log("findByIndex", findByIndex(data, index))
    node.msg = "Hello, World"; // Modify node
    break; // Get Only first matched node;
}
console.log("Find All Node ", [...findAllNode(data, "randomNode_1")])
Nur
  • 2,361
  • 2
  • 16
  • 34