4

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:[]}

2 Answers 2

2

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));

Sign up to request clarification or add additional context in comments.

Comments

-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
    , []) || [];
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.