skip to Main Content

I have a JS array that looks like this:

const arr = [
    {
        i: "tooltip_119",
        children: [
            {
                i: "text_345",
                children: []
            },
            {
                i: "wraper_375",
                children: [
                    {
                        i: "grid_15",
                        children: []
                    }
                ]             
            }
        ]
    },
    {
        i: "chart_123",
        children: []
    },
    {
        i: "graph_467",
        children: []
    },
]

The idea is that such an array can potentially have an infinite number of nestings. And I need a function that, taking the i parameter of some element, will return the i parameter of its parent (or 0 if the element is at the root and has no parents). An example of how such a function works:

console.log(findParent(arr, "grid_15"))  // returns "wraper_375"

I wrote a function like this:

export function findParent(arr, i) {   // this func has a bug on deep levels
  for (let j = 0; j < arr.length; j++) {
    const element = arr[j];
    if (element.children && element.children.length > 0) {
      const childElement = element.children.find((e) => e.i === i);
      if (childElement) {
        return element.i;
      } else {
        const parentElement = findParent(element.children, i);
        if (parentElement) {
          return parentElement.i;
        }
      }
    }
  }
  return 0;
}

The problem is that my function doesn’t work at deeper levels of nesting. I would be grateful for help
Expected outputs:

findParent(arr, "tooltip_119")  // 0
findParent(arr, "chart_123")  // 0
findParent(arr, "graph_467")  // 0
// 0 is returned because these elems do not have parent elem 

findParent(arr, "text_345")  // "tooltip_119"
findParent(arr, "wraper_375")  // "tooltip_119"

findParent(arr, "grid_15")  // "wraper_375"

3

Answers


  1. A simple recursion could be like that:

    const findParentId = (arr, id, parentId = 0) => {
      for(const {children, i} of arr){
        if(i === id){
          return parentId;
        }
        if(children.length){
          const childId = findParentId(children, id, i);
          if(childId){
            return childId;
          }
        }
      }  
    };
    
    ['wrong_id', 'tooltip_119', 'wraper_375', 'grid_15', 'second_childs_child', 'graph_467']
        .forEach(id => console.log(id, '=>', findParentId(arr, id)));
    <script>
    const arr = [
        {
            i: "tooltip_119",
            children: [
                {
                    i: "text_345",
                    children: []
                },
                {
                    i: "wraper_375",
                    children: [
                        {
                            i: "grid_15",
                            children: []
                        }
                    ]             
                }
            ]
        },
        {
            i: "chart_123",
            children: [{i: 'second_childs_child', children: []}]
        },
        {
            i: "graph_467",
            children: []
        },
    ]
    </script>
    Login or Signup to reply.
  2. For deep nesting, this data representation might not be the most effective. You may consider restructuring it and make your life easier.

    Especially if you would have to call this findParent function frequently, it might be worth migrating your array to a different structure, like so:

    const arr = [
        { i: "tooltip_119", parent: null },
        { i: "text_345", parent: "tooltip_119" },
        { i: "wraper_375", parent: "tooltip_119" },
        { i: "grid_15", parent: "wraper_375" },
        { i: "chart_123", parent: null },
        { i: "graph_467", parent: null }
    ];
    
    

    Then it’s just a lookup as compared to a search: O(1) instead of O(N) complexity. Hope this helps.

    Login or Signup to reply.
  3. Here is the working example:
    It returns the parent node (with all of its details) of found children element.

    const arr = [
      {
        i: "tooltip_119",
        children: [
          {
            i: "text_345",
            children: [],
          },
          {
            i: "wraper_375",
            children: [
              {
                i: "grid_15",
                children: [],
              },
            ],
          },
        ],
      },
      {
        i: "chart_123",
        children: [],
      },
      {
        i: "graph_467",
        children: [
          {
            i: "chart_1222",
            children: [],
          },
        ],
      },
    ];
    
    //solution: 
    
    function finder(arr, key, parent) {
      for (let elem of arr) {
        if (elem.i == key) return parent;
        if (elem.children.length > 0) {
          let foundParentNode = finder(elem.children, key, elem);
          if (foundParentNode) return foundParentNode;
        }
      }
    }
    
    let result = finder(arr, "grid_15", {});
    
    console.log(result.i);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search