Mohamed Usman
Mohamed Usman

Reputation: 43

Javascript find node from tree with recursive function

I have JavaScript tree data like this.

const tree = {
    children:[
        {id: 10, children: [{id: 34, children:[]}, {id: 35, children:[]}, {id: 36, children:[]}]},
        {id: 10, 
            children: [
                {id: 34, children:[
                        {id: 345, children:[]}
                    ]}, 
                {id: 35, children:[]}, 
                {id: 36, children:[]}
                ]
        },
        {id: 11, children: [{id: 30, children:[]}, {id: 33, children:[]}, {id: 3109, children:[]}]}
        ],
    id: 45
}

const getByID = (tree, id) => {
	let result = null
        if (id === tree.id) {
            return tree
        } else {
            if(tree.children){
                tree.children.forEach( node=> {
                    result = getByID(node, id)
                })
            }
            return result
        }
}

const find345 = getByID(tree, 345)
console.log(find345)

I was try to find item by its id from this tree. im using recursive function to iterate the tree and its children, but it wont find the item as i expected.

its always return null. expected to return {id: 345, children:[]}

Upvotes: 4

Views: 5101

Answers (2)

Geetha roshni
Geetha roshni

Reputation: 1

We can also use reduce method for recursive function

function findAllByKey(obj, keyToFind) {
  return Object.entries(obj)
    .reduce((acc, [key, value]) => (key === keyToFind)
      ? acc.concat(value)
      : (typeof value === 'object' && value)
      ? acc.concat(findAllByKey(value, keyToFind))
      : acc
    , []) || [];
}

Upvotes: -1

Nina Scholz
Nina Scholz

Reputation: 386776

You need to exit the loop by using a method which allows a short circuit on find.

The problem with visiting nodes but already found the node, is the replacement of the result with a later wrong result. You need to exit early with a found node.

Array#some allows to iterate and to exit the loop if a truty value is returned. In this case the result is truthy on find.

const tree = { children: [{ id: 10, children: [{ id: 34, children: [] }, { id: 35, children: [] }, { id: 36, children: [] }] }, { id: 10, children: [{ id: 34, children: [{ id: 345, children: [] }] }, { id: 35, children: [] }, { id: 36, children: [] }] }, { id: 11, children: [{ id: 30, children: [] }, { id: 33, children: [] }, { id: 3109, children: [] }] }], id: 45 };

const getByID = (tree, id) => {
	let result = null
        if (id === tree.id) {
            return tree
        } else {
            if(tree.children){
                tree.children.some(node => result = getByID(node, id));
                //            ^^^^                                      exit if found
                //                         ^^^^^^^^^^^^^^^^^^^^^^^^^^   return & assign
            }
            return result;
        }
}

const find345 = getByID(tree, 345)
console.log(find345)

A bit shorter

var tree = { children: [{ id: 10, children: [{ id: 34, children: [] }, { id: 35, children: [] }, { id: 36, children: [] }] }, { id: 10, children: [{ id: 34, children: [{ id: 345, children: [] }] }, { id: 35, children: [] }, { id: 36, children: [] }] }, { id: 11, children: [{ id: 30, children: [] }, { id: 33, children: [] }, { id: 3109, children: [] }] }], id: 45 },
    getByID = (tree, id) => {
        var temp;
        return tree.id === id
            ? tree
            : (tree.children || []).some(o => temp = getByID(o, id)) && temp;
    };

console.log(getByID(tree, 345));

Upvotes: 2

Related Questions