Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript find deeply nested objects

I need to filter objects recursively in a deeply nested array of objects using javascript, maybe with the help of lodash. What is the cleanest way to do it, If I don't know how many nested object there will be in my array?

Let's say I have the following structure

[
  {
    label: "first",
    id: 1,
    children: []
  },
  {
    label: "second",
    id: 2,
    children: [
      {
        label: "third",
        id: 3,
        children: [
          {
            label: "fifth",
            id: 5,
            children: []
          },
          {
            label: "sixth",
            id: 6,
            children: [
              {
                label: "seventh",
                id: 7,
                children: []
              }
            ]
          }
        ]
      },
      {
        label: "fourth",
        id: 4,
        children: []
      }
    ]
  }
];

I want to find the one with id 6, and if it has children return true otherwise false.

Of course If I have a similar data structure but with different number of items it should work too.

like image 861
ewool Avatar asked Nov 19 '18 20:11

ewool


People also ask

How do you find the value of an object nested in an array of objects?

How do I find the value of a nested object? If you need to search for a nested object, you can use Lodash's . find() function.It takes three arguments: collection : which can be either an array or object.

How do you check if a value exists in a nested object JavaScript?

var a; a = { b: { c: 'd' } }; function isset (fn) { var value; try { value = fn(); } catch (e) { value = undefined; } finally { return value !== undefined; } }; // ES5 console. log( isset(function () { return a. b.

How do I access nested objects?

The sub-properties of objects can be accessed by chaining together the dot or bracket notation .

How do I access nested arrays?

To access an element of the multidimensional array, you first use square brackets to access an element of the outer array that returns an inner array; and then use another square bracket to access the element of the inner array.


2 Answers

Since you only want a true of false answer you can use some() on the recursion, effectively doing a depth-first search, and make it pretty succinct:

let arr = [{label: "first",id: 1,children: []},{label: "second",id: 2,children: [{label: "third",id: 3,children: [{label: "fifth",id: 5,children: []},{label: "sixth",id: 6,children: [{label: "seventh",id: 7,children: []}]}]},{label: "fourth",id: 4,children: []}]}];

function findNested(arr, id) {
    let found = arr.find(node => node.id === id)
    return found 
      ? found.children.length > 0 
      : arr.some((c) => findNested(c.children, id))

} 

console.log(findNested(arr, 6))  // True: found with children
console.log(findNested(arr, 7))  // False: found no children
console.log(findNested(arr, 97)) // False: not found
like image 60
Mark Avatar answered Oct 13 '22 04:10

Mark


Perhaps a recursive solution along the lines of this might work for you? Here, the node with supplied id is recursively searched for through the 'children' of the supplied input data. If a child node with matching id is found, a boolean result is returned based on the existence of data in that nodes children array:

function nodeWithIdHasChildren(children, id) {
  
  for(const child of children) {

    // If this child node matches supplied id, then check to see if
    // it has data in it's children array and return true/false accordinly
    if(child.id === id) {
    
      if(Array.isArray(child.children) && child.children.length > 0) {
        return true
      }
      else {
        return false
      }
    }
    else {
    
      const result = nodeWithIdHasChildren(child.children, id);

      // If result returned from this recursion branch is not undefined
      // then assume it's true or false from a node matching the supplied
      // id. Pass the return result up the call stack
      if(result !== undefined) {
        return result
      }
    }
  }  
}

const data = [
  {
    label: "first",
    id: 1,
    children: []
  },
  {
    label: "second",
    id: 2,
    children: [
      {
        label: "third",
        id: 3,
        children: [
          {
            label: "fifth",
            id: 5,
            children: []
          },
          {
            label: "sixth",
            id: 6,
            children: [
              {
                label: "seventh",
                id: 7,
                children: []
              }
            ]
          }
        ]
      },
      {
        label: "fourth",
        id: 4,
        children: []
      }
    ]
  }
];



console.log('node 6 has children:', nodeWithIdHasChildren( data, 6 ) )

console.log('node 7 has children:', nodeWithIdHasChildren( data, 7 ) )

console.log('node 100 has children:', nodeWithIdHasChildren( data, 7 ), '(because node 100 does not exist)' )
like image 26
Dacre Denny Avatar answered Oct 13 '22 03:10

Dacre Denny