Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all parent in a nested object using recursion

I have the following object

const object = {
    id: "1",
    name: "a",
    children: [
        {
            id: "2",
            name: "b",
            children: [
                {
                    id: "3",
                    name: "c"
                }
            ]
        },
        {
            id: "4",
            name: "d"
        }
    ]
};

I need a function that accept the object and the id of the last child and return the path, for example, the following call: getPath(object, '3'); should return [{id: 1}, {id: 2}, {id: 3}].

I created the function but I can access only to the first parent.

function getPath(model, id, parent) {
    if (model == null) {
        return;
    }
    if (model.id === id) {
        console.log(model.id, parent.id)
    }
    if (model.children) {
        model.children.forEach(child => getPath(child, id, model));
    }
}

PS: The object has an unknown depth.

like image 825
Ayoub k Avatar asked Mar 29 '20 14:03

Ayoub k


2 Answers

You could use a short circuit for iterating the children and hand over the path from the function with the target object.

function getPath(model, id) {
    var path,
        item = { id: model.id };

    if (!model || typeof model !== 'object') return;

    if (model.id === id) return [item];    
    
    (model.children || []).some(child => path = getPath(child, id));
    return path && [item, ...path];
    
}
const object = { id: "1", name: "a", children: [{ id: "2", name: "b", children: [{ id: "3", name: "c" }] }, { id: "4", name: "d" }] };

console.log(getPath(object, '42')); // undefined
console.log(getPath(object, '3'));  // [{ id: 1 }, { id: 2 }, { id: 3 }]
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 71
Nina Scholz Avatar answered Sep 29 '22 09:09

Nina Scholz


This is pretty close. Consider passing the entire path array in your recursive function. The following is a slightly modified version of what you have that accomplishes this.

function getPath(model, id, path) {
    if (!path) {
      path = [];
    }

    if (model == null) {
        return;
    }
    if (model.id === id) {
        console.log(model.id, path)
    }
    if (model.children) {
        model.children.forEach(child => getPath(child, id, [...path, model.id]));
    }
}

const object = {
    id: "1",
    name: "a",
    children: [
        {
            id: "2",
            name: "b",
            children: [
                {
                    id: "3",
                    name: "c"
                }
            ]
        },
        {
            id: "4",
            name: "d"
        }
    ]
};

getPath(object, "3");
like image 29
Nick Avatar answered Sep 29 '22 09:09

Nick