-2

so I have an Arrray of objects :

[
  {
    MenuId: 'GM002',
    MenuName: 'Profile',
    MenuImage: 'CgProfile',
    Orderno: '2',
    SubMenuId: 'SM001',
    SubMenuName: 'Personal Information',
    SubMenuImage: 'BsPerson',
    SubMenuOrderno: '1',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
  },
  {
    MenuId: 'GM002',
    MenuName: 'Profile',
    MenuImage: 'CgProfile',
    Orderno: '2',
    SubMenuId: 'SM002',
    SubMenuName: 'Work',
    SubMenuImage: 'FcWorkflow',
    SubMenuOrderno: '2',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
  },
  {
    MenuId: 'GM002',
    MenuName: 'Profile',
    MenuImage: 'CgProfile',
    Orderno: '2',
    SubMenuId: 'SM005',
    SubMenuName: 'Document',
    SubMenuImage: 'GrDocumentText',
    SubMenuOrderno: '5',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
  },
  {
    MenuId: 'GM003',
    MenuName: 'Leave Request',
    MenuImage: 'FcLeave',
    Orderno: '3',
    SubMenuId: 'SM006',
    SubMenuName: 'Leave Log',
    SubMenuImage: 'MdOutlineHolidayVillage',
    SubMenuOrderno: '1',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
  },
  {
    MenuId: 'GM003',
    MenuName: 'Leave Request',
    MenuImage: 'FcLeave',
    Orderno: '3',
    SubMenuId: 'SM007',
    SubMenuName: 'Automation Log',
    SubMenuImage: 'TbSettingsAutomation',
    SubMenuOrderno: '2',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
  },
  {
    MenuId: 'GM003',
    MenuName: 'Leave Request',
    MenuImage: 'FcLeave',
    Orderno: '3',
    SubMenuId: 'SM008',
    SubMenuName: 'Rules',
    SubMenuImage: 'MdRule',
    SubMenuOrderno: '3',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
  }
]

but I want it like :

[
  {
    MenuId: 'GM002',
    MenuName: 'Profile',
    MenuImage: 'CgProfile',
    Orderno: '2',
    submenus : 
    [{
    SubMenuId: 'SM001',
    SubMenuName: 'Personal Information',
    SubMenuImage: 'BsPerson',
    SubMenuOrderno: '1',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
    },
    {
    SubMenuId: 'SM002',
    SubMenuName: 'Work',
    SubMenuImage: 'FcWorkflow',
    SubMenuOrderno: '2',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
    }]
  },
    {
    MenuId: 'GM003',
    MenuName: 'Leave Request',
    MenuImage: 'FcLeave',
    Orderno: '3',
    submenus : 
    [{
    SubMenuId: 'SM006',
    SubMenuName: 'Leave Log',
    SubMenuImage: 'MdOutlineHolidayVillage',
    SubMenuOrderno: '1',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
    },
    {
    SubMenuId: 'SM007',
    SubMenuName: 'Automation Log',
    SubMenuImage: 'TbSettingsAutomation',
    SubMenuOrderno: '2',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
    },
    {
    SubMenuId: 'SM008',
    SubMenuName: 'Rules',
    SubMenuImage: 'MdRule',
    SubMenuOrderno: '3',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
    },
    {
    SubMenuId: 'SM009',
    SubMenuName: 'Assets Request',
    SubMenuImage: 'MdWebAsset',
    SubMenuOrderno: '1',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
    }]
  }
]
Ele
  • 33,468
  • 7
  • 37
  • 75
  • 2
    Please use code sinppet. – Mina Jun 23 '22 at 17:29
  • Please post a specific example of where you're getting hung up – Tom Jun 23 '22 at 17:35
  • In other words, you want to make every property that begins with `Sub` to be inside an object called `submenus` ? and also combine them by value of `MenuId`? – IT goldman Jun 23 '22 at 17:37
  • so actually it is a response of my API . this data is coming from the database which is collected from three tables using joins . and the data is I have a menu which have it Id , Name , order number (represent as orderno) and the sub menu which have its own details .but you can see in my output I every time the menu details is repeating with the submenus detail. so I want it like, one object of menu having all its submenu in another array of objects (having the detail of submenus) as the value of it's submenu attribute , – Nisha Supyal Jun 24 '22 at 06:28

4 Answers4

1

There's endless ways you can do this, below is one approach.

function mergeSubmenus(arr) {
  return Object.values(arr.reduce((acc, {MenuId, MenuName, MenuImage, Orderno, ...rest}) => {
    const obj = acc[MenuId] ?? { MenuId, MenuName, MenuImage, Orderno, submenus: [] };
    obj.submenus.push(rest)
    
    acc[MenuId] = obj;
    return acc;
  }, {}));
}
Tom
  • 7,640
  • 1
  • 23
  • 47
0

You can use the function Array.prototype.reduce for grouping the objects and then use the function Object.values for extracting the grouped objects.

const arr = [  {    MenuId: 'GM002',    MenuName: 'Profile',    MenuImage: 'CgProfile',    Orderno: '2',    SubMenuId: 'SM001',    SubMenuName: 'Personal Information',    SubMenuImage: 'BsPerson',    SubMenuOrderno: '1',    SubSubMenuId: null,    SubSubMenuName: null,    SubSubMenuImage: null,    SubSubMenuOrderno: null  },  {    MenuId: 'GM002',    MenuName: 'Profile',    MenuImage: 'CgProfile',    Orderno: '2',    SubMenuId: 'SM002',    SubMenuName: 'Work',    SubMenuImage: 'FcWorkflow',    SubMenuOrderno: '2',    SubSubMenuId: null,    SubSubMenuName: null,    SubSubMenuImage: null,    SubSubMenuOrderno: null  },  {    MenuId: 'GM002',    MenuName: 'Profile',    MenuImage: 'CgProfile',    Orderno: '2',    SubMenuId: 'SM005',    SubMenuName: 'Document',    SubMenuImage: 'GrDocumentText',    SubMenuOrderno: '5',    SubSubMenuId: null,    SubSubMenuName: null,    SubSubMenuImage: null,    SubSubMenuOrderno: null  },  {    MenuId: 'GM003',    MenuName: 'Leave Request',    MenuImage: 'FcLeave',    Orderno: '3',    SubMenuId: 'SM006',    SubMenuName: 'Leave Log',    SubMenuImage: 'MdOutlineHolidayVillage',    SubMenuOrderno: '1',    SubSubMenuId: null,    SubSubMenuName: null,    SubSubMenuImage: null,    SubSubMenuOrderno: null  },  {    MenuId: 'GM003',    MenuName: 'Leave Request',    MenuImage: 'FcLeave',    Orderno: '3',    SubMenuId: 'SM007',    SubMenuName: 'Automation Log',    SubMenuImage: 'TbSettingsAutomation',    SubMenuOrderno: '2',    SubSubMenuId: null,    SubSubMenuName: null,    SubSubMenuImage: null,    SubSubMenuOrderno: null  },  {    MenuId: 'GM003',    MenuName: 'Leave Request',    MenuImage: 'FcLeave',    Orderno: '3',    SubMenuId: 'SM008',    SubMenuName: 'Rules',    SubMenuImage: 'MdRule',    SubMenuOrderno: '3',    SubSubMenuId: null,    SubSubMenuName: null,    SubSubMenuImage: null,    SubSubMenuOrderno: null  }],
      result = Object.values(arr.reduce((a, {MenuId, MenuName, MenuImage, Orderno, ...submenus}) => {
        (a[MenuId] ?? (a[MenuId] = {MenuId, MenuName, MenuImage, Orderno, submenus: []})).submenus.push(submenus);
        return a;
      }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ele
  • 33,468
  • 7
  • 37
  • 75
0

const data = [{
    MenuId: 'GM002',
    MenuName: 'Profile',
    MenuImage: 'CgProfile',
    Orderno: '2',
    SubMenuId: 'SM001',
    SubMenuName: 'Personal Information',
    SubMenuImage: 'BsPerson',
    SubMenuOrderno: '1',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
}, {
    MenuId: 'GM002',
    MenuName: 'Profile',
    MenuImage: 'CgProfile',
    Orderno: '2',
    SubMenuId: 'SM002',
    SubMenuName: 'Work',
    SubMenuImage: 'FcWorkflow',
    SubMenuOrderno: '2',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
}, {
    MenuId: 'GM002',
    MenuName: 'Profile',
    MenuImage: 'CgProfile',
    Orderno: '2',
    SubMenuId: 'SM005',
    SubMenuName: 'Document',
    SubMenuImage: 'GrDocumentText',
    SubMenuOrderno: '5',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
}, {
    MenuId: 'GM003',
    MenuName: 'Leave Request',
    MenuImage: 'FcLeave',
    Orderno: '3',
    SubMenuId: 'SM006',
    SubMenuName: 'Leave Log',
    SubMenuImage: 'MdOutlineHolidayVillage',
    SubMenuOrderno: '1',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
}, {
    MenuId: 'GM003',
    MenuName: 'Leave Request',
    MenuImage: 'FcLeave',
    Orderno: '3',
    SubMenuId: 'SM007',
    SubMenuName: 'Automation Log',
    SubMenuImage: 'TbSettingsAutomation',
    SubMenuOrderno: '2',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
}, {
    MenuId: 'GM003',
    MenuName: 'Leave Request',
    MenuImage: 'FcLeave',
    Orderno: '3',
    SubMenuId: 'SM008',
    SubMenuName: 'Rules',
    SubMenuImage: 'MdRule',
    SubMenuOrderno: '3',
    SubSubMenuId: null,
    SubSubMenuName: null,
    SubSubMenuImage: null,
    SubSubMenuOrderno: null
}]


const result = data.reduce((acc, item) => {
  const itemInAcc = acc.find(accItem => accItem.MenuId === item.MenuId)
  // the item already exist.
  if (itemInAcc) {
    itemInAcc.submenus.push({
        SubMenuId: item.SubMenuId,
        SubMenuName: item.SubMenuName,
        SubMenuImage: item.SubMenuImage,
        SubMenuOrderno: item.SubMenuOrderno,
        SubSubMenuId: item.SubSubMenuId,
        SubSubMenuName: item.SubSubMenuName,
        SubSubMenuImage: item.SubSubMenuImage,
        SubSubMenuOrderno: item.SubSubMenuOrderno
    })
  } else {
   const pushedItem = {
    MenuId: item.MenuId,
    MenuName: item.MenuName,
    MenuImage: item.MenuImage,
    Orderno: item.Orderno,
    submenus: [{
        SubMenuId: item.SubMenuId,
        SubMenuName: item.SubMenuName,
        SubMenuImage: item.SubMenuImage,
        SubMenuOrderno: item.SubMenuOrderno,
        SubSubMenuId: item.SubSubMenuId,
        SubSubMenuName: item.SubSubMenuName,
        SubSubMenuImage: item.SubSubMenuImage,
        SubSubMenuOrderno: item.SubSubMenuOrderno
    }]
   }
   acc.push(pushedItem)
  }
  return acc
}, [])

console.log(result)
Mina
  • 14,386
  • 3
  • 13
  • 26
0

If you're using the library underscore you could do something like this (removed properties for sake of example)

_.map(_.groupBy(arr, x => x.MenuId), item => item)
.map(x => {
    return {
        'MenuId': x[0].MenuId,
        'MenuName': x[0].MenuName,
        'SubMenu': x.map(y => {
            return {
                'SubMenuId': y.SubMenuId,
                'SubMenuName': y.SubMenuName
            }
        })
    }
});

If not, you can just create a polyfill for groupBy.

Here's a popular one I found, though it could be a bit complex to understand.

NavalRishi
  • 124
  • 9