Hierarchical Tree

by Nalin Sajwan

JavaScript

console.time("Overall time");
const data = [
  'Hemiptera/Mirida/Nalin Sajwan',
  'Hemiptera/Miridae/Neophloeobia/incisa',
  'Lepidoptera/Nymphalidae/Ephinephile/rawnsleyi',
  'a/af1/af1g1/af1g1s1',
  'a/af1/af1g1/af1g1s2',
  'a/af1/af1g1/af1g1s3',
  'a/af1/af1g2/af1g2s1',
  'a/af1/af1g2/af1g2s2',
  'a/af2/af2g1/af2g1s1',
  'a/af2/af2g1/af2g2s1',
  'a/af3/af3g1/af3g1s1',
];

const taxonomies = data.map((v) => v.split("/"));

const addToHierarchy = (val, level, hierarchy) => {
  if (val[level]) {
    if (!hierarchy.hasOwnProperty(val[level])) {
      hierarchy[val[level]] = {};
    }
    addToHierarchy(val, level + 1, hierarchy[val[level]]);
  }
};

let working = {};

for (var i = 0; i < taxonomies.length; i++) {
  addToHierarchy(taxonomies[i], 0, working);
};

// To convert object of leaf node to 0.
working = JSON.parse(JSON.stringify( working ).split("{}").join("0"));

console.log("\nhierarchical json ==> ", JSON.stringify(working, null, 4));

const separator = '>';

const remapHierarchy = (item, parent) => {
  const children = [];
  for (let k in item) {
    let obj = { "name": k };
      
    console.log("\n\nk ==> ", k);
    console.log("parent ==> ", parent);
    
    if (typeof parent !== "undefined" && parent.trim() !== "") {
      obj.parentNames = parent;
      parent = parent + separator + k;
    } else {
      obj.parentNames = null;
      parent = k;
    }
    
    console.log("loop parent ==> ", parent);

    const subData = remapHierarchy(item[k], parent);
    
    if (obj.parentNames !== null)
      obj.parentNames = obj.parentNames;

    if (subData.length > 0)     
      obj.children = subData;
    
    children.push(obj);
  }

  return children;
}

const hierarchy = remapHierarchy(working);

// console.log("hierarchical array ==> \n",JSON.stringify(hierarchy.children, null, 4));

const countLastChildren = (arr) => {
  if(arr.children) {
    var return_val = 0;
    arr.children.forEach(function(el){
      return_val += countLastChildren(el);
   ...