Search code examples
javascriptarraysdata-structurestreebinary-tree

Restructure data dynamically to treedata in Javascript


I have an array of actors and each of them have arrays like movies, awards and so on. I want to change the structure of my data that I receive from the server into a tree data. My array name should be in a new array children that has 3 properties: a self generated id, name which is the name of my array for example 'movies', and children which contains the actual data for my array. I need a head start to create this dynamically because my data can grow. Any help is much appreciated.

data structure from the server:

[{
    name: 'Tom Holland',
    id: 1,
    movies: [{
      typename: 'MoviesData',
      id: 12,
      name: 'Spider-Man NWH',
      stars: 4
    }, {
      typename: 'MoviesData',
      id: 13,
      name: 'Spider-Man Far from Home',
      stars: 4
    }],
    awards: [{
      typename: 'AwardsData',
      id: 6,
      name: 'BAFTA Award',
      year: 2017
    }, {
      typename: 'AwardsData',
      id: 7,
      name: 'Empire Award',
      year: 2013
    }], //... more Arrays like Hobbies, TV-Shows, etc...
  }, //... more Actors
]

required tree data:

[{
    name: "Tom Holland",
    id: 1,
    children: [{
      id: 3, // self generated id for each array
      name: "Movies", // Object key name
      children: [
                   {typename: 'MoviesData', id: 12, name: 'Spider-Man NWH', stars: 4},
                   {typename: 'MoviesData', id: 13, name: 'Spider-Man Far from Home', stars: 4},...
                   ]
    }, {
      id: 15, // self generated id
      name: "Awards",
      children: [
                   {typename:'AwardsData', id: 6, name: 'BAFTA Award', year: 2017},
                   {typename:'AwardsData', id: 7, name: 'Empire Award', value: 2013},...
                   ]
    }, //...]
  }, //...]

Solution

  • Presented below is one possible way to achieve the desired objective.

    Code Snippet

    const myTransform = arr => (
      arr.map(
        ({name, id, ...rest}) => ({
          name, id,
          children: [
            ...Object.entries(rest)
            .map(([name, v], idx) => ({
              name,
              id: ++idx,
              // Math.floor(Math.random() * 10),    // if "id" has to be random
              children: v
            }))
          ]
        })
      )
    );
    
    /* Code with explanation
    // method to transform given array
    const myTransform = arr => (
      arr.map(      // iterate using ".map()"
        ({name, id, ...rest}) => ({     // destructure name, id & rest
          name, id,               // keep name, id as-is
          children: [             // transform "rest" into an array
            ...Object.entries(rest)  // "rest" is an object, iterate over its key-value pairs
            .map(([name, v], idx) => ({     // track the index as "idx"
              name,               // transform k-v pair to have "name" prop
              id: ++idx,          // this is the "self-generated" id as needed
              // in case one needs it to be random, instead of "++idx", use below
              // Math.floor(Math.random() * 10),
              children: v         // move the array to nested children
            }))
          ]
        })
      )
    );
    
    */
    
    const dataArr = [{
        name: 'Tom Holland',
        id: 1,
        Movies: [{
          typename: 'MoviesData',
          id: 12,
          name: 'Spider-Man NWH',
          stars: 4
        }, {
          typename: 'MoviesData',
          id: 13,
          name: 'Spider-Man Far from Home',
          stars: 4
        }],
        Awards: [{
          typename: 'AwardsData',
          id: 6,
          name: 'BAFTA Award',
          year: 2017
        }, {
          typename: 'AwardsData',
          id: 7,
          name: 'Empire Award',
          year: 2013
        }], //... more Arrays like Hobbies, TV-Shows, etc...
      }, //... more Actors
    ];
    
    console.log(
      'transformed array:\n',
      myTransform(dataArr)
    );
    .as-console-wrapper { max-height: 100% !important; top: 0 }

    Explanation

    Inline comments added to the snippet above.