简体   繁体   中英

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.

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

I'm not sure if I'm missing something about what's required here, but it looks like you were pretty close to me:

 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"}]; const trim_item = ({ name, url }) => ({ name, url }); 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 [trim_item(item), ...array]; } } } return null; } console.log('link2', findObject(data, 'link2')); console.log('link5', findObject(data, 'link5')); console.log('link10', findObject(data, 'link10')); console.log('link99', findObject(data, 'link99'));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM