wonderful world
wonderful world

Reputation: 11599

Algorithm to convert a table data to hierarchical tree data using Javascript ECMAScript 6

I have a JSON table data and want to convert to JSON tree data as shown below. I'm looking for an efficient algorithm in JavaScript using any new ECMAScript 6 operator or statements with a functional approach (not by standard recursive algorithm with ES5)?

Table data:

[
   {
      "Children":"4th Grand Father"
   },
   {
      "Name":"4th Grand Father",
      "Children":"3rd Grand Father"
   },
   {
      "Name":"3rd Grand Father",
      "Children":"2nd Grand Father"
   },
   {
      "Name":"2nd Grand Father",
      "Children":"Grand Father"
   },
   {
      "Name":"Grand Father",
      "Children":"Father"
   },
   {
      "Name":"Grand Father",
      "Children":"Uncle"
   },
   {
      "Name":"Uncle",
      "Children":"Cousin"
   },
   {
      "Name":"Father",
      "Children":"Brother"
   },
   {
      "Name":"Father",
      "Children":"Me"
   }
]

Tree data:

[
  {
    "Name": "4th Grand Father",
    "Children": [
      {
        "Name": "3rd Grand Father",
        "Children": [
          {
            "Name": "2nd Grand Father",
            "Children": [
              {
                "Name": "Grand Father",
                "Children": [
                  {
                    "Name": "Father",
                    "children": [
                      {
                        "Name": "Brother"
                      },
                      {
                        "Name": "Me"
                      }
                    ]
                  },
                  {
                    "Name": "Uncle",
                    "children": [
                      {
                        "Name": "Cousin"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
]

Upvotes: 1

Views: 1111

Answers (1)

trincot
trincot

Reputation: 350137

You could use this ES6 function, which uses a Map, arrow functions, destructured argument assignment. You could even replace the concat call by spread syntax, but I don't think that brings any benefit:

const makeTree = (data) => {
    const hash = data.reduce ( (acc, {Name, Children}) => 
        acc.set(Name, (acc.get(Name) || []).concat(Children)) 
    , new Map );

    const recurse = (Name) => hash.has(Name)
            ?   { Name, Children: hash.get(Name).map(recurse) }
            :   { Name };
    return recurse(undefined).Children;
}

// Sample data
const data = [
   {
      "Children":"4th Grand Father"
   },
   {
      "Name":"4th Grand Father",
      "Children":"3rd Grand Father"
   },
   {
      "Name":"3rd Grand Father",
      "Children":"2nd Grand Father"
   },
   {
      "Name":"2nd Grand Father",
      "Children":"Grand Father"
   },
   {
      "Name":"Grand Father",
      "Children":"Father"
   },
   {
      "Name":"Grand Father",
      "Children":"Uncle"
   },
   {
      "Name":"Uncle",
      "Children":"Cousin"
   },
   {
      "Name":"Father",
      "Children":"Brother"
   },
   {
      "Name":"Father",
      "Children":"Me"
   }
];

const result = makeTree(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Explanation:

The hash variable is built from an empty Map, adding the records to it keyed by Name. The value linked to each key is the children information, as an array. When the same Name is encountered (i.e. acc.get(Name) returns something), the child is added to the already existing array, otherwise (|| []) an empty array is created and the child is added to that.

Once the hash is complete, the top of the hierarchy is taken by its missing Name (undefined), and through recursion the children are looked up in the hash and added to the final object.

As the result object is an object with a Children array, and the desired outcome was in fact that array, it is the Children property that gets returned.

Upvotes: 3

Related Questions