Search code examples
javascriptobjectfilterlodash

Find branches in nested Object in Javascript


I have tried to find a solution for my problem in the last two hours, which included trying myself, scanning lodash docs as well as SO for any suitable answer, but did not come up with anything remotely working or practical. I would be very grateful for help.

I have an object that can be any depth.

e.g.

{
  "name": "alpha",
  "children": [
    {
      "name": "beta",
      "children": [
        {
          "name": "gamma",
          "children": [
            {
              "name": "delta",
              "children": []
            }
          ]
        }
      ]
    },
    {
      "name": "epsilon",
      "children": [
        {
          "name": "zeta",
          "children": [
            {
              "name": "eta",
              "children": []
            }
          ]
        }
      ]
    }
  ]
}

I am looking for a function which will return the whole branch of this object where there is a matching name (if possible without lodash but if really needed its ok).

Given an input of 'gamma' I expect it to return


{
  "name": "alpha",
  "children": [
    {
      "name": "beta",
      "children": [
        {
          "name": "gamma",
          "children": [
            {
              "name": "delta",
              "children": []
            }
          ]
        }
      ]
    }
  ]
}

Given an input 't' I expect it to return the whole object, since it is included in the names of children in both branches.


Solution

  • You can separate this problem into two parts, first let's test if the name is present in the tree:

    function hasStr(item, str) {
      return item.name.includes(str) || item.children.some(x => hasStr(x, str));
    }
    
    hasStr(item, 'gamma'); // true
    

    You also asked to have a function that returns the passed object and return only a filtered version of the children:

    function possibleAnswer(item, str) {
      return {
        name: item.name,
        children: item.children.filter(x => hasStr(x, str)),
      };
    }
    
    possibleAnswer(item, 'gamma'); // will return desired object