javascript find deeply nested objects












2















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.










share|improve this question























  • You can write a function that can iterate over the top-level items, and then modify that function to accept an input array to iterate over, and then have that function call itself recursively for each item's children.

    – meagar
    Nov 19 '18 at 20:12











  • are any of the children refs to parents? that can cause an infinite loop when iterating. otherwise, it's a pretty straight-forward for/in, recursively calling if the typeof all[specific] =='object.

    – dandavis
    Nov 19 '18 at 20:15
















2















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.










share|improve this question























  • You can write a function that can iterate over the top-level items, and then modify that function to accept an input array to iterate over, and then have that function call itself recursively for each item's children.

    – meagar
    Nov 19 '18 at 20:12











  • are any of the children refs to parents? that can cause an infinite loop when iterating. otherwise, it's a pretty straight-forward for/in, recursively calling if the typeof all[specific] =='object.

    – dandavis
    Nov 19 '18 at 20:15














2












2








2








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.










share|improve this question














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.







javascript lodash






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 19 '18 at 20:11









ewoolewool

323




323













  • You can write a function that can iterate over the top-level items, and then modify that function to accept an input array to iterate over, and then have that function call itself recursively for each item's children.

    – meagar
    Nov 19 '18 at 20:12











  • are any of the children refs to parents? that can cause an infinite loop when iterating. otherwise, it's a pretty straight-forward for/in, recursively calling if the typeof all[specific] =='object.

    – dandavis
    Nov 19 '18 at 20:15



















  • You can write a function that can iterate over the top-level items, and then modify that function to accept an input array to iterate over, and then have that function call itself recursively for each item's children.

    – meagar
    Nov 19 '18 at 20:12











  • are any of the children refs to parents? that can cause an infinite loop when iterating. otherwise, it's a pretty straight-forward for/in, recursively calling if the typeof all[specific] =='object.

    – dandavis
    Nov 19 '18 at 20:15

















You can write a function that can iterate over the top-level items, and then modify that function to accept an input array to iterate over, and then have that function call itself recursively for each item's children.

– meagar
Nov 19 '18 at 20:12





You can write a function that can iterate over the top-level items, and then modify that function to accept an input array to iterate over, and then have that function call itself recursively for each item's children.

– meagar
Nov 19 '18 at 20:12













are any of the children refs to parents? that can cause an infinite loop when iterating. otherwise, it's a pretty straight-forward for/in, recursively calling if the typeof all[specific] =='object.

– dandavis
Nov 19 '18 at 20:15





are any of the children refs to parents? that can cause an infinite loop when iterating. otherwise, it's a pretty straight-forward for/in, recursively calling if the typeof all[specific] =='object.

– dandavis
Nov 19 '18 at 20:15












9 Answers
9






active

oldest

votes


















5














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








share|improve this answer





















  • 1





    I think that instead of (found && ...) || it would be more logical to do found ? ... : since if the element was found if makes no sense to still execute arr.some if the found node has no children.

    – trincot
    Nov 19 '18 at 20:40






  • 1





    @trincot || has short-circuiting behavior so it doesn't execute the arr.some().

    – Patrick Roberts
    Nov 19 '18 at 20:42






  • 2





    @PatrickRoberts I think he means for the case where found exists but has no children. Doesn't make sense to do DFS after that. Having said that, nice solution :)

    – slider
    Nov 19 '18 at 20:45






  • 1





    As slider said ^^^^ "...if the found node has no children"

    – trincot
    Nov 19 '18 at 20:45








  • 1





    I decided to go with your solution, and it works flawlessly without any issue, thanks!

    – ewool
    Nov 22 '18 at 18:22



















1














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)' )








share|improve this answer

































    0














    also:



    function explore(myArray, searchedId) {
    for (let i=0; i<myArray.length; i++) {
    let el;
    if (myArray[i].id == searchedId) {
    el = myArray[i];
    } else {
    el = explore(myArray[i].children, searchedId);
    }
    if (el) {
    return el.children.length > 0;
    }
    }
    }





    share|improve this answer































      0














      You can use "recursion" like below to check if id has children or not






      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 hasChildren(arr, id) {
      let res = false
      for (let d of arr) {
      if(d.id == id) return d.children.length > 0
      res = res || hasChildren(d.children, id)
      if(res) return true
      }
      return res
      }

      console.log('id 4 has children? ', hasChildren(arr, 4))
      console.log('id 6 has children? ', hasChildren(arr, 6))








      share|improve this answer

































        0














        You can do it using three simple javascript functions:



        // Function to Flatten results
        var flattenAll = function(data) {
        var result = ;
        var flatten = function(arr) {
        _.forEach(arr, function(a) {
        result.push(a);
        flatten(a.children);
        });
        };
        flatten(data);
        return result;
        };

        // Function to search on flattened array
        var search = function(flattened, id) {
        var found = _.find(flattened, function(d) {
        return d.id == id;
        });
        return found;
        };

        // Function to check if element is found and have children
        var hasChildren = function(element) {
        return element && element.children && element.children.length > 0;
        }

        // Usage, search for id = 6
        hasChildren(search(flattenAll(your_data_object), 6))


        Plunker






        share|improve this answer































          0














          You can use a generator function to iterate the nodes recursively and simplify your logic for checking existence by using Array.prototype.some():






          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:}]}];

          function * nodes (array) {
          for (const node of array) {
          yield node;
          yield * nodes(node.children);
          }
          }

          const array = Array.from(nodes(data));

          console.log(array.some(node => node.id === 6 && node.children.length > 0));
          console.log(array.some(node => node.id === 7 && node.children.length > 0));








          share|improve this answer































            0














            Here is another solution using recursion and doing it via only one Array.find:






            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:  } ] } ];

            const search = (data, id) => {
            var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
            s(data, id)
            return f ? f.children.length > 0 : false
            }

            console.log(search(data, 6)) // True: found with children
            console.log(search(data, 7)) // False: found but has no children
            console.log(search(data, 15)) // False: not found at all





            The idea is to have a recursive function which when finds the id remembers the object.



            Once we have the found (or we know we do not have an entry found) just return the children array length or return false.



            If you want to actually return the found object instead of the boolean for children.length:






            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:  } ] } ];

            const search = (data, id) => {
            var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
            s(data, id)
            return f
            }

            console.log(search(data, 6)) // returns only the object with id:6
            console.log(search(data, 7)) // returns only the object with id: 7
            console.log(search(data, 71)) // returns undefined since nothing was found








            share|improve this answer

































              0














              The JSON.parse reviver parameter or the JSON.stringify replacer parameter can be used to check all values, and generate flat id lookup object with references to the nodes :




              var lookup = {}, json = '[{"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":}]}]'

              var result = JSON.parse(json, (key, val) => val.id ? lookup[val.id] = val : val);

              console.log( 'id: 2, children count:', lookup[2].children.length )
              console.log( 'id: 6, children count:', lookup[6].children.length )
              console.log( lookup )








              share|improve this answer

































                0














                I suggest to use deepdash extension for lodash:



                var id6HasChildren = _.filterDeep(arr,
                function(value, key, path, depth, parent) {
                if (key == 'children' && parent.id == 6 && value.length) return true;
                },
                { leafsOnly: false }
                ).length>0;


                Here is a docs for filterDeep.



                And this a full test for your case.






                share|improve this answer























                  Your Answer






                  StackExchange.ifUsing("editor", function () {
                  StackExchange.using("externalEditor", function () {
                  StackExchange.using("snippets", function () {
                  StackExchange.snippets.init();
                  });
                  });
                  }, "code-snippets");

                  StackExchange.ready(function() {
                  var channelOptions = {
                  tags: "".split(" "),
                  id: "1"
                  };
                  initTagRenderer("".split(" "), "".split(" "), channelOptions);

                  StackExchange.using("externalEditor", function() {
                  // Have to fire editor after snippets, if snippets enabled
                  if (StackExchange.settings.snippets.snippetsEnabled) {
                  StackExchange.using("snippets", function() {
                  createEditor();
                  });
                  }
                  else {
                  createEditor();
                  }
                  });

                  function createEditor() {
                  StackExchange.prepareEditor({
                  heartbeatType: 'answer',
                  autoActivateHeartbeat: false,
                  convertImagesToLinks: true,
                  noModals: true,
                  showLowRepImageUploadWarning: true,
                  reputationToPostImages: 10,
                  bindNavPrevention: true,
                  postfix: "",
                  imageUploader: {
                  brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                  contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                  allowUrls: true
                  },
                  onDemand: true,
                  discardSelector: ".discard-answer"
                  ,immediatelyShowMarkdownHelp:true
                  });


                  }
                  });














                  draft saved

                  draft discarded


















                  StackExchange.ready(
                  function () {
                  StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53381935%2fjavascript-find-deeply-nested-objects%23new-answer', 'question_page');
                  }
                  );

                  Post as a guest















                  Required, but never shown

























                  9 Answers
                  9






                  active

                  oldest

                  votes








                  9 Answers
                  9






                  active

                  oldest

                  votes









                  active

                  oldest

                  votes






                  active

                  oldest

                  votes









                  5














                  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








                  share|improve this answer





















                  • 1





                    I think that instead of (found && ...) || it would be more logical to do found ? ... : since if the element was found if makes no sense to still execute arr.some if the found node has no children.

                    – trincot
                    Nov 19 '18 at 20:40






                  • 1





                    @trincot || has short-circuiting behavior so it doesn't execute the arr.some().

                    – Patrick Roberts
                    Nov 19 '18 at 20:42






                  • 2





                    @PatrickRoberts I think he means for the case where found exists but has no children. Doesn't make sense to do DFS after that. Having said that, nice solution :)

                    – slider
                    Nov 19 '18 at 20:45






                  • 1





                    As slider said ^^^^ "...if the found node has no children"

                    – trincot
                    Nov 19 '18 at 20:45








                  • 1





                    I decided to go with your solution, and it works flawlessly without any issue, thanks!

                    – ewool
                    Nov 22 '18 at 18:22
















                  5














                  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








                  share|improve this answer





















                  • 1





                    I think that instead of (found && ...) || it would be more logical to do found ? ... : since if the element was found if makes no sense to still execute arr.some if the found node has no children.

                    – trincot
                    Nov 19 '18 at 20:40






                  • 1





                    @trincot || has short-circuiting behavior so it doesn't execute the arr.some().

                    – Patrick Roberts
                    Nov 19 '18 at 20:42






                  • 2





                    @PatrickRoberts I think he means for the case where found exists but has no children. Doesn't make sense to do DFS after that. Having said that, nice solution :)

                    – slider
                    Nov 19 '18 at 20:45






                  • 1





                    As slider said ^^^^ "...if the found node has no children"

                    – trincot
                    Nov 19 '18 at 20:45








                  • 1





                    I decided to go with your solution, and it works flawlessly without any issue, thanks!

                    – ewool
                    Nov 22 '18 at 18:22














                  5












                  5








                  5







                  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








                  share|improve this answer















                  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








                  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





                  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






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 19 '18 at 20:49

























                  answered Nov 19 '18 at 20:33









                  Mark MeyerMark Meyer

                  38.5k33159




                  38.5k33159








                  • 1





                    I think that instead of (found && ...) || it would be more logical to do found ? ... : since if the element was found if makes no sense to still execute arr.some if the found node has no children.

                    – trincot
                    Nov 19 '18 at 20:40






                  • 1





                    @trincot || has short-circuiting behavior so it doesn't execute the arr.some().

                    – Patrick Roberts
                    Nov 19 '18 at 20:42






                  • 2





                    @PatrickRoberts I think he means for the case where found exists but has no children. Doesn't make sense to do DFS after that. Having said that, nice solution :)

                    – slider
                    Nov 19 '18 at 20:45






                  • 1





                    As slider said ^^^^ "...if the found node has no children"

                    – trincot
                    Nov 19 '18 at 20:45








                  • 1





                    I decided to go with your solution, and it works flawlessly without any issue, thanks!

                    – ewool
                    Nov 22 '18 at 18:22














                  • 1





                    I think that instead of (found && ...) || it would be more logical to do found ? ... : since if the element was found if makes no sense to still execute arr.some if the found node has no children.

                    – trincot
                    Nov 19 '18 at 20:40






                  • 1





                    @trincot || has short-circuiting behavior so it doesn't execute the arr.some().

                    – Patrick Roberts
                    Nov 19 '18 at 20:42






                  • 2





                    @PatrickRoberts I think he means for the case where found exists but has no children. Doesn't make sense to do DFS after that. Having said that, nice solution :)

                    – slider
                    Nov 19 '18 at 20:45






                  • 1





                    As slider said ^^^^ "...if the found node has no children"

                    – trincot
                    Nov 19 '18 at 20:45








                  • 1





                    I decided to go with your solution, and it works flawlessly without any issue, thanks!

                    – ewool
                    Nov 22 '18 at 18:22








                  1




                  1





                  I think that instead of (found && ...) || it would be more logical to do found ? ... : since if the element was found if makes no sense to still execute arr.some if the found node has no children.

                  – trincot
                  Nov 19 '18 at 20:40





                  I think that instead of (found && ...) || it would be more logical to do found ? ... : since if the element was found if makes no sense to still execute arr.some if the found node has no children.

                  – trincot
                  Nov 19 '18 at 20:40




                  1




                  1





                  @trincot || has short-circuiting behavior so it doesn't execute the arr.some().

                  – Patrick Roberts
                  Nov 19 '18 at 20:42





                  @trincot || has short-circuiting behavior so it doesn't execute the arr.some().

                  – Patrick Roberts
                  Nov 19 '18 at 20:42




                  2




                  2





                  @PatrickRoberts I think he means for the case where found exists but has no children. Doesn't make sense to do DFS after that. Having said that, nice solution :)

                  – slider
                  Nov 19 '18 at 20:45





                  @PatrickRoberts I think he means for the case where found exists but has no children. Doesn't make sense to do DFS after that. Having said that, nice solution :)

                  – slider
                  Nov 19 '18 at 20:45




                  1




                  1





                  As slider said ^^^^ "...if the found node has no children"

                  – trincot
                  Nov 19 '18 at 20:45







                  As slider said ^^^^ "...if the found node has no children"

                  – trincot
                  Nov 19 '18 at 20:45






                  1




                  1





                  I decided to go with your solution, and it works flawlessly without any issue, thanks!

                  – ewool
                  Nov 22 '18 at 18:22





                  I decided to go with your solution, and it works flawlessly without any issue, thanks!

                  – ewool
                  Nov 22 '18 at 18:22













                  1














                  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)' )








                  share|improve this answer






























                    1














                    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)' )








                    share|improve this answer




























                      1












                      1








                      1







                      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)' )








                      share|improve this answer















                      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)' )








                      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)' )





                      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)' )






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Nov 19 '18 at 20:42

























                      answered Nov 19 '18 at 20:24









                      Dacre DennyDacre Denny

                      12.1k41031




                      12.1k41031























                          0














                          also:



                          function explore(myArray, searchedId) {
                          for (let i=0; i<myArray.length; i++) {
                          let el;
                          if (myArray[i].id == searchedId) {
                          el = myArray[i];
                          } else {
                          el = explore(myArray[i].children, searchedId);
                          }
                          if (el) {
                          return el.children.length > 0;
                          }
                          }
                          }





                          share|improve this answer




























                            0














                            also:



                            function explore(myArray, searchedId) {
                            for (let i=0; i<myArray.length; i++) {
                            let el;
                            if (myArray[i].id == searchedId) {
                            el = myArray[i];
                            } else {
                            el = explore(myArray[i].children, searchedId);
                            }
                            if (el) {
                            return el.children.length > 0;
                            }
                            }
                            }





                            share|improve this answer


























                              0












                              0








                              0







                              also:



                              function explore(myArray, searchedId) {
                              for (let i=0; i<myArray.length; i++) {
                              let el;
                              if (myArray[i].id == searchedId) {
                              el = myArray[i];
                              } else {
                              el = explore(myArray[i].children, searchedId);
                              }
                              if (el) {
                              return el.children.length > 0;
                              }
                              }
                              }





                              share|improve this answer













                              also:



                              function explore(myArray, searchedId) {
                              for (let i=0; i<myArray.length; i++) {
                              let el;
                              if (myArray[i].id == searchedId) {
                              el = myArray[i];
                              } else {
                              el = explore(myArray[i].children, searchedId);
                              }
                              if (el) {
                              return el.children.length > 0;
                              }
                              }
                              }






                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Nov 19 '18 at 20:29









                              AndreaAndrea

                              404414




                              404414























                                  0














                                  You can use "recursion" like below to check if id has children or not






                                  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 hasChildren(arr, id) {
                                  let res = false
                                  for (let d of arr) {
                                  if(d.id == id) return d.children.length > 0
                                  res = res || hasChildren(d.children, id)
                                  if(res) return true
                                  }
                                  return res
                                  }

                                  console.log('id 4 has children? ', hasChildren(arr, 4))
                                  console.log('id 6 has children? ', hasChildren(arr, 6))








                                  share|improve this answer






























                                    0














                                    You can use "recursion" like below to check if id has children or not






                                    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 hasChildren(arr, id) {
                                    let res = false
                                    for (let d of arr) {
                                    if(d.id == id) return d.children.length > 0
                                    res = res || hasChildren(d.children, id)
                                    if(res) return true
                                    }
                                    return res
                                    }

                                    console.log('id 4 has children? ', hasChildren(arr, 4))
                                    console.log('id 6 has children? ', hasChildren(arr, 6))








                                    share|improve this answer




























                                      0












                                      0








                                      0







                                      You can use "recursion" like below to check if id has children or not






                                      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 hasChildren(arr, id) {
                                      let res = false
                                      for (let d of arr) {
                                      if(d.id == id) return d.children.length > 0
                                      res = res || hasChildren(d.children, id)
                                      if(res) return true
                                      }
                                      return res
                                      }

                                      console.log('id 4 has children? ', hasChildren(arr, 4))
                                      console.log('id 6 has children? ', hasChildren(arr, 6))








                                      share|improve this answer















                                      You can use "recursion" like below to check if id has children or not






                                      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 hasChildren(arr, id) {
                                      let res = false
                                      for (let d of arr) {
                                      if(d.id == id) return d.children.length > 0
                                      res = res || hasChildren(d.children, id)
                                      if(res) return true
                                      }
                                      return res
                                      }

                                      console.log('id 4 has children? ', hasChildren(arr, 4))
                                      console.log('id 6 has children? ', hasChildren(arr, 6))








                                      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 hasChildren(arr, id) {
                                      let res = false
                                      for (let d of arr) {
                                      if(d.id == id) return d.children.length > 0
                                      res = res || hasChildren(d.children, id)
                                      if(res) return true
                                      }
                                      return res
                                      }

                                      console.log('id 4 has children? ', hasChildren(arr, 4))
                                      console.log('id 6 has children? ', hasChildren(arr, 6))





                                      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 hasChildren(arr, id) {
                                      let res = false
                                      for (let d of arr) {
                                      if(d.id == id) return d.children.length > 0
                                      res = res || hasChildren(d.children, id)
                                      if(res) return true
                                      }
                                      return res
                                      }

                                      console.log('id 4 has children? ', hasChildren(arr, 4))
                                      console.log('id 6 has children? ', hasChildren(arr, 6))






                                      share|improve this answer














                                      share|improve this answer



                                      share|improve this answer








                                      edited Nov 19 '18 at 20:34

























                                      answered Nov 19 '18 at 20:29









                                      Nitish NarangNitish Narang

                                      2,9401815




                                      2,9401815























                                          0














                                          You can do it using three simple javascript functions:



                                          // Function to Flatten results
                                          var flattenAll = function(data) {
                                          var result = ;
                                          var flatten = function(arr) {
                                          _.forEach(arr, function(a) {
                                          result.push(a);
                                          flatten(a.children);
                                          });
                                          };
                                          flatten(data);
                                          return result;
                                          };

                                          // Function to search on flattened array
                                          var search = function(flattened, id) {
                                          var found = _.find(flattened, function(d) {
                                          return d.id == id;
                                          });
                                          return found;
                                          };

                                          // Function to check if element is found and have children
                                          var hasChildren = function(element) {
                                          return element && element.children && element.children.length > 0;
                                          }

                                          // Usage, search for id = 6
                                          hasChildren(search(flattenAll(your_data_object), 6))


                                          Plunker






                                          share|improve this answer




























                                            0














                                            You can do it using three simple javascript functions:



                                            // Function to Flatten results
                                            var flattenAll = function(data) {
                                            var result = ;
                                            var flatten = function(arr) {
                                            _.forEach(arr, function(a) {
                                            result.push(a);
                                            flatten(a.children);
                                            });
                                            };
                                            flatten(data);
                                            return result;
                                            };

                                            // Function to search on flattened array
                                            var search = function(flattened, id) {
                                            var found = _.find(flattened, function(d) {
                                            return d.id == id;
                                            });
                                            return found;
                                            };

                                            // Function to check if element is found and have children
                                            var hasChildren = function(element) {
                                            return element && element.children && element.children.length > 0;
                                            }

                                            // Usage, search for id = 6
                                            hasChildren(search(flattenAll(your_data_object), 6))


                                            Plunker






                                            share|improve this answer


























                                              0












                                              0








                                              0







                                              You can do it using three simple javascript functions:



                                              // Function to Flatten results
                                              var flattenAll = function(data) {
                                              var result = ;
                                              var flatten = function(arr) {
                                              _.forEach(arr, function(a) {
                                              result.push(a);
                                              flatten(a.children);
                                              });
                                              };
                                              flatten(data);
                                              return result;
                                              };

                                              // Function to search on flattened array
                                              var search = function(flattened, id) {
                                              var found = _.find(flattened, function(d) {
                                              return d.id == id;
                                              });
                                              return found;
                                              };

                                              // Function to check if element is found and have children
                                              var hasChildren = function(element) {
                                              return element && element.children && element.children.length > 0;
                                              }

                                              // Usage, search for id = 6
                                              hasChildren(search(flattenAll(your_data_object), 6))


                                              Plunker






                                              share|improve this answer













                                              You can do it using three simple javascript functions:



                                              // Function to Flatten results
                                              var flattenAll = function(data) {
                                              var result = ;
                                              var flatten = function(arr) {
                                              _.forEach(arr, function(a) {
                                              result.push(a);
                                              flatten(a.children);
                                              });
                                              };
                                              flatten(data);
                                              return result;
                                              };

                                              // Function to search on flattened array
                                              var search = function(flattened, id) {
                                              var found = _.find(flattened, function(d) {
                                              return d.id == id;
                                              });
                                              return found;
                                              };

                                              // Function to check if element is found and have children
                                              var hasChildren = function(element) {
                                              return element && element.children && element.children.length > 0;
                                              }

                                              // Usage, search for id = 6
                                              hasChildren(search(flattenAll(your_data_object), 6))


                                              Plunker







                                              share|improve this answer












                                              share|improve this answer



                                              share|improve this answer










                                              answered Nov 19 '18 at 21:15









                                              Marcos BriganteMarcos Brigante

                                              859822




                                              859822























                                                  0














                                                  You can use a generator function to iterate the nodes recursively and simplify your logic for checking existence by using Array.prototype.some():






                                                  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:}]}];

                                                  function * nodes (array) {
                                                  for (const node of array) {
                                                  yield node;
                                                  yield * nodes(node.children);
                                                  }
                                                  }

                                                  const array = Array.from(nodes(data));

                                                  console.log(array.some(node => node.id === 6 && node.children.length > 0));
                                                  console.log(array.some(node => node.id === 7 && node.children.length > 0));








                                                  share|improve this answer




























                                                    0














                                                    You can use a generator function to iterate the nodes recursively and simplify your logic for checking existence by using Array.prototype.some():






                                                    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:}]}];

                                                    function * nodes (array) {
                                                    for (const node of array) {
                                                    yield node;
                                                    yield * nodes(node.children);
                                                    }
                                                    }

                                                    const array = Array.from(nodes(data));

                                                    console.log(array.some(node => node.id === 6 && node.children.length > 0));
                                                    console.log(array.some(node => node.id === 7 && node.children.length > 0));








                                                    share|improve this answer


























                                                      0












                                                      0








                                                      0







                                                      You can use a generator function to iterate the nodes recursively and simplify your logic for checking existence by using Array.prototype.some():






                                                      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:}]}];

                                                      function * nodes (array) {
                                                      for (const node of array) {
                                                      yield node;
                                                      yield * nodes(node.children);
                                                      }
                                                      }

                                                      const array = Array.from(nodes(data));

                                                      console.log(array.some(node => node.id === 6 && node.children.length > 0));
                                                      console.log(array.some(node => node.id === 7 && node.children.length > 0));








                                                      share|improve this answer













                                                      You can use a generator function to iterate the nodes recursively and simplify your logic for checking existence by using Array.prototype.some():






                                                      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:}]}];

                                                      function * nodes (array) {
                                                      for (const node of array) {
                                                      yield node;
                                                      yield * nodes(node.children);
                                                      }
                                                      }

                                                      const array = Array.from(nodes(data));

                                                      console.log(array.some(node => node.id === 6 && node.children.length > 0));
                                                      console.log(array.some(node => node.id === 7 && node.children.length > 0));








                                                      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:}]}];

                                                      function * nodes (array) {
                                                      for (const node of array) {
                                                      yield node;
                                                      yield * nodes(node.children);
                                                      }
                                                      }

                                                      const array = Array.from(nodes(data));

                                                      console.log(array.some(node => node.id === 6 && node.children.length > 0));
                                                      console.log(array.some(node => node.id === 7 && node.children.length > 0));





                                                      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:}]}];

                                                      function * nodes (array) {
                                                      for (const node of array) {
                                                      yield node;
                                                      yield * nodes(node.children);
                                                      }
                                                      }

                                                      const array = Array.from(nodes(data));

                                                      console.log(array.some(node => node.id === 6 && node.children.length > 0));
                                                      console.log(array.some(node => node.id === 7 && node.children.length > 0));






                                                      share|improve this answer












                                                      share|improve this answer



                                                      share|improve this answer










                                                      answered Nov 19 '18 at 23:11









                                                      Patrick RobertsPatrick Roberts

                                                      20.1k33576




                                                      20.1k33576























                                                          0














                                                          Here is another solution using recursion and doing it via only one Array.find:






                                                          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:  } ] } ];

                                                          const search = (data, id) => {
                                                          var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                          s(data, id)
                                                          return f ? f.children.length > 0 : false
                                                          }

                                                          console.log(search(data, 6)) // True: found with children
                                                          console.log(search(data, 7)) // False: found but has no children
                                                          console.log(search(data, 15)) // False: not found at all





                                                          The idea is to have a recursive function which when finds the id remembers the object.



                                                          Once we have the found (or we know we do not have an entry found) just return the children array length or return false.



                                                          If you want to actually return the found object instead of the boolean for children.length:






                                                          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:  } ] } ];

                                                          const search = (data, id) => {
                                                          var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                          s(data, id)
                                                          return f
                                                          }

                                                          console.log(search(data, 6)) // returns only the object with id:6
                                                          console.log(search(data, 7)) // returns only the object with id: 7
                                                          console.log(search(data, 71)) // returns undefined since nothing was found








                                                          share|improve this answer






























                                                            0














                                                            Here is another solution using recursion and doing it via only one Array.find:






                                                            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:  } ] } ];

                                                            const search = (data, id) => {
                                                            var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                            s(data, id)
                                                            return f ? f.children.length > 0 : false
                                                            }

                                                            console.log(search(data, 6)) // True: found with children
                                                            console.log(search(data, 7)) // False: found but has no children
                                                            console.log(search(data, 15)) // False: not found at all





                                                            The idea is to have a recursive function which when finds the id remembers the object.



                                                            Once we have the found (or we know we do not have an entry found) just return the children array length or return false.



                                                            If you want to actually return the found object instead of the boolean for children.length:






                                                            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:  } ] } ];

                                                            const search = (data, id) => {
                                                            var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                            s(data, id)
                                                            return f
                                                            }

                                                            console.log(search(data, 6)) // returns only the object with id:6
                                                            console.log(search(data, 7)) // returns only the object with id: 7
                                                            console.log(search(data, 71)) // returns undefined since nothing was found








                                                            share|improve this answer




























                                                              0












                                                              0








                                                              0







                                                              Here is another solution using recursion and doing it via only one Array.find:






                                                              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:  } ] } ];

                                                              const search = (data, id) => {
                                                              var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                              s(data, id)
                                                              return f ? f.children.length > 0 : false
                                                              }

                                                              console.log(search(data, 6)) // True: found with children
                                                              console.log(search(data, 7)) // False: found but has no children
                                                              console.log(search(data, 15)) // False: not found at all





                                                              The idea is to have a recursive function which when finds the id remembers the object.



                                                              Once we have the found (or we know we do not have an entry found) just return the children array length or return false.



                                                              If you want to actually return the found object instead of the boolean for children.length:






                                                              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:  } ] } ];

                                                              const search = (data, id) => {
                                                              var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                              s(data, id)
                                                              return f
                                                              }

                                                              console.log(search(data, 6)) // returns only the object with id:6
                                                              console.log(search(data, 7)) // returns only the object with id: 7
                                                              console.log(search(data, 71)) // returns undefined since nothing was found








                                                              share|improve this answer















                                                              Here is another solution using recursion and doing it via only one Array.find:






                                                              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:  } ] } ];

                                                              const search = (data, id) => {
                                                              var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                              s(data, id)
                                                              return f ? f.children.length > 0 : false
                                                              }

                                                              console.log(search(data, 6)) // True: found with children
                                                              console.log(search(data, 7)) // False: found but has no children
                                                              console.log(search(data, 15)) // False: not found at all





                                                              The idea is to have a recursive function which when finds the id remembers the object.



                                                              Once we have the found (or we know we do not have an entry found) just return the children array length or return false.



                                                              If you want to actually return the found object instead of the boolean for children.length:






                                                              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:  } ] } ];

                                                              const search = (data, id) => {
                                                              var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                              s(data, id)
                                                              return f
                                                              }

                                                              console.log(search(data, 6)) // returns only the object with id:6
                                                              console.log(search(data, 7)) // returns only the object with id: 7
                                                              console.log(search(data, 71)) // returns undefined since nothing was found








                                                              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:  } ] } ];

                                                              const search = (data, id) => {
                                                              var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                              s(data, id)
                                                              return f ? f.children.length > 0 : false
                                                              }

                                                              console.log(search(data, 6)) // True: found with children
                                                              console.log(search(data, 7)) // False: found but has no children
                                                              console.log(search(data, 15)) // False: not found at all





                                                              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:  } ] } ];

                                                              const search = (data, id) => {
                                                              var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                              s(data, id)
                                                              return f ? f.children.length > 0 : false
                                                              }

                                                              console.log(search(data, 6)) // True: found with children
                                                              console.log(search(data, 7)) // False: found but has no children
                                                              console.log(search(data, 15)) // False: not found at all





                                                              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:  } ] } ];

                                                              const search = (data, id) => {
                                                              var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                              s(data, id)
                                                              return f
                                                              }

                                                              console.log(search(data, 6)) // returns only the object with id:6
                                                              console.log(search(data, 7)) // returns only the object with id: 7
                                                              console.log(search(data, 71)) // returns undefined since nothing was found





                                                              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:  } ] } ];

                                                              const search = (data, id) => {
                                                              var f, s = (d, id) => d.find(x => x.id == id ? f = x : s(x.children, id))
                                                              s(data, id)
                                                              return f
                                                              }

                                                              console.log(search(data, 6)) // returns only the object with id:6
                                                              console.log(search(data, 7)) // returns only the object with id: 7
                                                              console.log(search(data, 71)) // returns undefined since nothing was found






                                                              share|improve this answer














                                                              share|improve this answer



                                                              share|improve this answer








                                                              edited Nov 19 '18 at 23:52

























                                                              answered Nov 19 '18 at 22:08









                                                              AkrionAkrion

                                                              9,43511224




                                                              9,43511224























                                                                  0














                                                                  The JSON.parse reviver parameter or the JSON.stringify replacer parameter can be used to check all values, and generate flat id lookup object with references to the nodes :




                                                                  var lookup = {}, json = '[{"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":}]}]'

                                                                  var result = JSON.parse(json, (key, val) => val.id ? lookup[val.id] = val : val);

                                                                  console.log( 'id: 2, children count:', lookup[2].children.length )
                                                                  console.log( 'id: 6, children count:', lookup[6].children.length )
                                                                  console.log( lookup )








                                                                  share|improve this answer






























                                                                    0














                                                                    The JSON.parse reviver parameter or the JSON.stringify replacer parameter can be used to check all values, and generate flat id lookup object with references to the nodes :




                                                                    var lookup = {}, json = '[{"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":}]}]'

                                                                    var result = JSON.parse(json, (key, val) => val.id ? lookup[val.id] = val : val);

                                                                    console.log( 'id: 2, children count:', lookup[2].children.length )
                                                                    console.log( 'id: 6, children count:', lookup[6].children.length )
                                                                    console.log( lookup )








                                                                    share|improve this answer




























                                                                      0












                                                                      0








                                                                      0







                                                                      The JSON.parse reviver parameter or the JSON.stringify replacer parameter can be used to check all values, and generate flat id lookup object with references to the nodes :




                                                                      var lookup = {}, json = '[{"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":}]}]'

                                                                      var result = JSON.parse(json, (key, val) => val.id ? lookup[val.id] = val : val);

                                                                      console.log( 'id: 2, children count:', lookup[2].children.length )
                                                                      console.log( 'id: 6, children count:', lookup[6].children.length )
                                                                      console.log( lookup )








                                                                      share|improve this answer















                                                                      The JSON.parse reviver parameter or the JSON.stringify replacer parameter can be used to check all values, and generate flat id lookup object with references to the nodes :




                                                                      var lookup = {}, json = '[{"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":}]}]'

                                                                      var result = JSON.parse(json, (key, val) => val.id ? lookup[val.id] = val : val);

                                                                      console.log( 'id: 2, children count:', lookup[2].children.length )
                                                                      console.log( 'id: 6, children count:', lookup[6].children.length )
                                                                      console.log( lookup )








                                                                      var lookup = {}, json = '[{"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":}]}]'

                                                                      var result = JSON.parse(json, (key, val) => val.id ? lookup[val.id] = val : val);

                                                                      console.log( 'id: 2, children count:', lookup[2].children.length )
                                                                      console.log( 'id: 6, children count:', lookup[6].children.length )
                                                                      console.log( lookup )





                                                                      var lookup = {}, json = '[{"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":}]}]'

                                                                      var result = JSON.parse(json, (key, val) => val.id ? lookup[val.id] = val : val);

                                                                      console.log( 'id: 2, children count:', lookup[2].children.length )
                                                                      console.log( 'id: 6, children count:', lookup[6].children.length )
                                                                      console.log( lookup )






                                                                      share|improve this answer














                                                                      share|improve this answer



                                                                      share|improve this answer








                                                                      edited Nov 20 '18 at 9:09

























                                                                      answered Nov 20 '18 at 8:59









                                                                      SlaiSlai

                                                                      15.3k32335




                                                                      15.3k32335























                                                                          0














                                                                          I suggest to use deepdash extension for lodash:



                                                                          var id6HasChildren = _.filterDeep(arr,
                                                                          function(value, key, path, depth, parent) {
                                                                          if (key == 'children' && parent.id == 6 && value.length) return true;
                                                                          },
                                                                          { leafsOnly: false }
                                                                          ).length>0;


                                                                          Here is a docs for filterDeep.



                                                                          And this a full test for your case.






                                                                          share|improve this answer




























                                                                            0














                                                                            I suggest to use deepdash extension for lodash:



                                                                            var id6HasChildren = _.filterDeep(arr,
                                                                            function(value, key, path, depth, parent) {
                                                                            if (key == 'children' && parent.id == 6 && value.length) return true;
                                                                            },
                                                                            { leafsOnly: false }
                                                                            ).length>0;


                                                                            Here is a docs for filterDeep.



                                                                            And this a full test for your case.






                                                                            share|improve this answer


























                                                                              0












                                                                              0








                                                                              0







                                                                              I suggest to use deepdash extension for lodash:



                                                                              var id6HasChildren = _.filterDeep(arr,
                                                                              function(value, key, path, depth, parent) {
                                                                              if (key == 'children' && parent.id == 6 && value.length) return true;
                                                                              },
                                                                              { leafsOnly: false }
                                                                              ).length>0;


                                                                              Here is a docs for filterDeep.



                                                                              And this a full test for your case.






                                                                              share|improve this answer













                                                                              I suggest to use deepdash extension for lodash:



                                                                              var id6HasChildren = _.filterDeep(arr,
                                                                              function(value, key, path, depth, parent) {
                                                                              if (key == 'children' && parent.id == 6 && value.length) return true;
                                                                              },
                                                                              { leafsOnly: false }
                                                                              ).length>0;


                                                                              Here is a docs for filterDeep.



                                                                              And this a full test for your case.







                                                                              share|improve this answer












                                                                              share|improve this answer



                                                                              share|improve this answer










                                                                              answered Jan 15 at 18:50









                                                                              Yuri GorYuri Gor

                                                                              653413




                                                                              653413






























                                                                                  draft saved

                                                                                  draft discarded




















































                                                                                  Thanks for contributing an answer to Stack Overflow!


                                                                                  • Please be sure to answer the question. Provide details and share your research!

                                                                                  But avoid



                                                                                  • Asking for help, clarification, or responding to other answers.

                                                                                  • Making statements based on opinion; back them up with references or personal experience.


                                                                                  To learn more, see our tips on writing great answers.




                                                                                  draft saved


                                                                                  draft discarded














                                                                                  StackExchange.ready(
                                                                                  function () {
                                                                                  StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53381935%2fjavascript-find-deeply-nested-objects%23new-answer', 'question_page');
                                                                                  }
                                                                                  );

                                                                                  Post as a guest















                                                                                  Required, but never shown





















































                                                                                  Required, but never shown














                                                                                  Required, but never shown












                                                                                  Required, but never shown







                                                                                  Required, but never shown

































                                                                                  Required, but never shown














                                                                                  Required, but never shown












                                                                                  Required, but never shown







                                                                                  Required, but never shown







                                                                                  Popular posts from this blog

                                                                                  Guess what letter conforming each word

                                                                                  Port of Spain

                                                                                  Run scheduled task as local user group (not BUILTIN)