Search code examples
javascriptdomrecursionchildrendepth

Get the child with biggest depth of a parent


Say I have this tree structure:

-root
|
|
|-child1
 |
 |-innerChild1
 |
 |-innerChild2
|
|-child2

I would like to make a JS function that takes an element of the tree, and see from its perspective how deep does it go. For instance:

    var depth = getInnerDepth(root);
    depth = 3;

Depth equals 3, because root as parent at depth 1, has first degree children at depth2, and one of them (child1) has children at depth 3.

    var depth = getInnerDepth(child1);
    depth = 2;

Depth equals 2, because child1 is considered the parent in this case, so its depth is 1. Child1 has children, so the result is 2.

   var depth = getInnerDepth(innerChild1);
   depth = 1;

Depth equals 1, because from the prespective of innerChild1, it does not have any children, so it has a depth of 1.

I imagine this should be implemented recursively, but i have trouble thinking of a good way to do it.

 function getInnerDepth(parent){ 
   var depth = 1; 
   if (parent.hasChildren) {
    depth++;
    parent.children.forEach(function(child){ getInnerDepth(child); }) 
   }
   return depth;
  }

Something along the lines of this. (I know that this is not working :-) ).


Solution

  • I believe this would work as required, assuming that the .children property is an array, based on the OP's usage of .forEach in their attempt:

    function getInnerDepth(node) {
        if (node.hasChildren) {
            var depths = node.children.map(getInnerDepth);
            return 1 + Math.max.apply(Math, depths);
        } else {
            return 1;
        }
    } 
    

    Example using the DOM just for illustration (small tweaks required, because children in the DOM isn't really an array):

    function getInnerDepth(node) {
      if (node.children.length) {
        var depths = Array.prototype.map.call(node.children, getInnerDepth);
        return 1 + Math.max.apply(Math, depths);
      } else {
        return 1;
      }
    }
    
    document.body.addEventListener("click", function(e) {
      console.log("Depth: ", getInnerDepth(e.target));
    }, false);
    div:not(.as-console-wrapper) {
      padding-left: 2em;
      border: 1px solid black;
    }
    <div>
      Root
      <div>
        Child 1
        <div>
          Sub-child 1-1
        </div>
        <div>
          Sub-child 1-2
          <div>
            Sub-child 1-2-1
          </div>
        </div>
      </div>
      <div>
        Child 2
      </div>
    </div>