Home > database >  Map array of objects with matching records in Javascript
Map array of objects with matching records in Javascript

Time:04-12

I have array of objects inside which I have items and attachments as separated.

Current Behaviour:

const data = {
   id: 1,
   name: 'Test',
   attachments: [
   {id: 1, itemId: -1, attachmentName: 'hello.jpg'},
   {id: 2, itemId: -1, attachmentName: 'world.jpg'},
   {id: 3, itemId: 2, attachmentName: 'image.jpg'}
   ],
   items: [
    {id: -1, itemName: 'Item One'},
    {id: 2, itemName: 'Item Two'},
   ]
}

console.log('data ', data);

Here to map attachments with items, we have itemId inside each attachment which will map with id of each item.

Expected Result:

 const data = {
   id: 1,
   name: 'Test',
   items: [
    { 
      id: -1, 
      itemName: 'Item One',  
      attachments: [
       {id: 1, itemId: -1, attachmentName: 'hello.jpg'},
       {id: 2, itemId: -1, attachmentName: 'world.jpg'}
     ]
    },
    {
     id: 2, 
     itemName: 'Item Two', 
     attachements: [
      {id: 3, itemId: 2, attachmentName: 'image.jpg'}
     ]
   },
  ]
}

Things I have tried,

const results = data.attachments.reduce((results, item) => {
    (results[item.id] = results[item.id] || []).push(item);
    return results;
}, {});

Tried grouping each attachment based on Id, but this doesn't come along way.

Could someone kindly help to achieve the desired output?

Big thanks in advance.

CodePudding user response:

You could create a Map keyed by itemId, with the item objects as corresponding values, where each object gets an attachments array that is initially empty.

Then iterate the data to populate those attachment arrays.

Finally get the objects from the Map to construct the final object:

const data = {id: 1,name: 'Test',attachments: [{id: 1, itemId: -1, attachmentName: 'hello.jpg'},{id: 2, itemId: -1, attachmentName: 'world.jpg'},{id: 3, itemId: 2, attachmentName: 'image.jpg'}],items: [{id: -1, itemName: 'Item One'},{id: 2, itemName: 'Item One'},]}

const {items, attachments, ...rest} = data;
const map = new Map(items.map(item => [item.id, {...item, attachments: []}]));
for (const attachment of attachments) {
    map.get(attachment.itemId).attachments.push(attachment);
}
const result = {...rest, items: [...map.values()]};

console.log(result);

  • Related