Map over Javascript array and transform objects in it to a specific format?

Viewed 124

I have an array of objects

const mainArray = [{
    name: 'main name',
    id: 'main id',
    parent: [{
      name: 'parent name',
      id: '1'
    }],
    child: [{
      name: 'child name',
      id: 'child id'
    }]
  }, {
    name: 'main name 2',
    id: 'main id 2',
    parent: [{
      name: 'parent name',
      id: '1'
    }],
    child: [{
      name: 'child name 2',
      id: 'child id 2'
    }]
  },
  {
    name: 'main name 3',
    id: 'main id 3',
    parent: [{
      name: 'parent name something else',
      id: '2'
    }],
    child: [{
      name: 'child name 3',
      id: 'child id 3'
    }]
  }
]

I need to bring it to this form

const resultArray = [{
  key: 'main',
  title: 'main name',
}, {
  key: 'parent',
  title: 'parent name'
}, {
  key: 'child',
  title: 'child name'
}]

So far I got this

if (mainArray) {
   mainArray.map((main) => {
     if (main.child && main.child.length) {
       if (main.parent && main.parent.length) {
         main.parent.map((item) => {
           data.push({
             key: 'parent',
             title: item.name
           });
         });
       }

       data.push({
         key: 'main',
         title: main.name
       });

       main.child.map((item) => {
         data.push({
           key: 'child',
           title: item.name
         });
       });
     }
   });
 }

And then I take this data array to display if a table and it looks like this

enter image description here

My problem is - two mains can be different but have the same parent (parents have the same ids) and then I don't need to add the parent to array two times, and I need it to be displayed like this

enter image description here

So I'm looking to a way to if two parents objects have the same id to merge them together so that in the final array there will be only one parent and the main and the child of that parent get stuck to one parent instead of two identical ones

Here the link to jsfiddle

I can use lodash

1 Answers

You could first group by parent and return an object where each key is parent name, then from that object you can create an array.

const mainArray = [{"name":"main name","id":"main id","parent":[{"name":"parent name","id":"1"}],"child":[{"name":"child name","id":"child id"}]},{"name":"main name 2","id":"main id 2","parent":[{"name":"parent name","id":"1"}],"child":[{"name":"child name 2","id":"child id 2"}]},{"name":"main name 3","id":"main id 3","parent":[{"name":"parent name something else","id":"2"}],"child":[{"name":"child name 3","id":"child id 3"}]}]


function children(rest, child) {
  const result = [{
    key: 'main',
    title: rest.name
  }];
  result.push(...child.map(({
    name
  }) => ({
    key: 'child',
    title: name
  })))
  return result;
}

const groupByParent = mainArray.reduce((r, {
  parent,
  child,
  ...rest
}) => {
  parent.forEach(p => {
    if (!r[p.name]) {
      r[p.name] = [{
          key: 'parent',
          title: p.name
        },
        ...children(rest, child)
      ]
    } else {
      r[p.name].push(...children(rest, child));
    }
  })

  return r;
}, {})

const result = Object.values(groupByParent).flat()
console.log(result)

Related