Skip to content
Advertisement

How to find path from tree of nodes

Consider a data structure similar to the one below:

[
    { name: 'Link1', url: 'link1', },
    { name: 'Link2', url: 'link2', },
    {
        name: 'Link3', url: 'link3',
        submenu: [
            { name: 'Link4', url: 'link4', },
            { name: 'Link5', url: 'link5', },
        ]
    },
    { name: 'Link6', url: 'link6', },
    {
        name: 'Link6', url: 'link6',
        submenu: [
            { name: 'Link7', url: 'link7', },
            {
                name: 'Link8', url: 'link8',
                submenu: [
                    { name: 'Link9', url: 'link9', },
                    { name: 'Link10', url: 'link10', },
                ]
            },
        ]
    },
    { name: 'Link11', url: 'link11', },
    { name: 'Link12', url: 'link12', },
]

The function I have tried is as follows using recursion.

function findObject(obj, element) {
    for (const item of obj) {
        if (item.url === element) {
            return [item];
        }
        if (item.submenu) {
            const array = findObject(item.submenu, element);
            if (array) {
                return array;
            }
        }

    }
}
let output = findObject(data, 'link10')
console.log(output);

I am getting an output: [{name: 'Link10', url: 'link10'}]

I would like to get an output as follows:

[{ name: 'Link1', url: 'link1', }, { name: 'Link6', url: 'link6' }, { name: 'Link8', url: 'link8' }, { name: 'Link10', url: 'link10', }]

And if I call the function as follows:

let output = findObject(data, 'link11')
console.log(output);

Should return results as [{name: 'Link11', url: 'link11',}]

I tried the following as well and using array methods as well but to no success:

function findObject(obj, element) {
    for (const item of obj) {
        if (item.url === element) {
            return [item];
        }
        // if (item.submenu){
        //     const array = findObject(item.submenu, element);
        //     if(array){
        //         return array;
        //     }
        // }
        const array = findObject(item.submenu, element);
        if (array) {
            return [item, ...array];
        }
    }
}

Which gives me result of ($_$w, obj) isn’t iterable. Appreciate if one could explain, Where I am going wrong and how to wrap my head around this problem.

Advertisement

Answer

I am glad, Al least you tried to solve your problem yourself!

This is very interesting question. Because its a path finding situation.

Lets say we need to found correct path, Now When ever we found any path, we write down that path no in our notebook.

Now there is 2 way, we choose 1st path, I found out that this is wrong path, So we tried 2nd path, and so on…

If we found any correct path we need to stop looking for new path and by looking notebook, We can found the correct path…

I am terrible at explaining, Lets look at the code,

const data = [{ name: 'Link1', url: 'link1', }, { name: 'Link2', url: 'link2', }, { name: 'Link3', url: 'link3', submenu: [{ name: 'Link4', url: 'link4', }, { name: 'Link5', url: 'link5', },] }, { name: 'Link6', url: 'link6', }, { name: 'Link6', url: 'link6', submenu: [{ name: 'Link7', url: 'link7', }, { name: 'Link8', url: 'link8', submenu: [{ name: 'Link9', url: 'link9', }, { name: 'Link10', url: 'link10', },] },] }, { name: 'Link11', url: 'link11', }, { name: 'Link12', url: 'link12', },]

function createTree(data, element) {
    const nodes = { item: null, child: null }
    for (const { name, submenu, url } of data) {
        if (url == element) {
            nodes.item = { name, url }
            break
        }
        if (submenu) {
            const result = createTree(submenu, element);
            if (result.item) {
                nodes.item = { name, url }
                nodes.child = result;
                break
            }
        }
    }
    return nodes;
}
function findObject(data, element) {
    let result = [], tree = createTree(data, element);

    while (tree) {
        result.push(tree.item)
        tree = tree.child;
    }
    if (result.length > 1) result.unshift(data[0]);

    return result;
}
console.log('link2', findObject(data, 'link2'));
console.log('link5', findObject(data, 'link5'));
console.log('link10', findObject(data, 'link10'));
console.log('link99', findObject(data, 'link99'));
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement