How to use the result of an iteration to re-iterate?

Tags: , ,



I need to create a new array from another with the condition: for example from an array

mainArr: [
        {
            "id":1,
            "name":"root"
        },
        {
            "id":2,
            "parentId":1,
            "name":"2"
        },
        {
            "id":148,
            "parentId":2,
            "name":"3"
        },
        {
            "id":151,
            "parentId":148,
            "name":"4"
        },
        {
            "id":152,
            "parentId":151,
            "name":"5"
        }
    ]

I need to make an array ['1','2','148','151'] which means the path from “parentId”‘s to “id”:152 – (argument for this function).

I think main logic can be like this:

const parentsArr = [];
mainArr.forEach((item) => {
    if (item.id === id) {
        parentsArr.unshift(`${item.parentId}`);
    }

and the result {item.parentId} should be used to iterate again. But I don’t understand how to do it…

Answer

You could use a recursive function for this. First you can transform your array to a Map, where each id from each object points to its object. Doing this allows you to .get() the object with a given id efficiently. For each object, you can get the parentId, and if it is defined, rerun your traverse() object again searching for the parent id. When you can no longer find a parentid, then you’re at the root, meaning you can return an empty array to signify no parentid object exist:

const arr = [{"id":1,"name":"root"},{"id":2,"parentId":1,"name":"2"},{"id":148,"parentId":2,"name":"3"},{"id":151,"parentId":148,"name":"4"},{"id":152,"parentId":151,"name":"5"}];

const transform = arr => new Map(arr.map((o) => [o.id, o]));

const traverse = (map, id) => {
  const startObj = map.get(+id);
  if("parentId" in startObj)
    return [...traverse(map, startObj.parentId), startObj.parentId]; 
  else
    return [];
}

console.log(traverse(transform(arr), "152"));

If you want to include “152” in the result, you can change your recursive function to use the id argument, and change the base-case to return [id] (note that the + in front of id is used to convert it to a number if it is a string):

const arr = [{"id":1,"name":"root"},{"id":2,"parentId":1,"name":"2"},{"id":148,"parentId":2,"name":"3"},{"id":151,"parentId":148,"name":"4"},{"id":152,"parentId":151,"name":"5"}];

const transform = arr => new Map(arr.map((o) => [o.id, o]));

const traverse = (map, id) => {
  const startObj = map.get(+id);
  if("parentId" in startObj)
    return [...traverse(map, startObj.parentId), +id]; 
  else
    return [+id];
}

console.log(traverse(transform(arr), "152"));


Source: stackoverflow