Group all the objects together having the same value for the '_id' key in JavaScript

Suppose we have an array of objects like this −

const arr = [
   {_id : "1", S : "2"},
   {_id : "1", M : "4"},
   {_id : "2", M : "1"},
   {_id : "" , M : "1"},
   {_id : "3", S : "3"}
];

We are required to write a JavaScript function that takes in one such array and groups all the objects together that have the same value for the '_id' key.

Therefore, the final output should look something like this −

const output = [
   {_id : "1", M : "4", S : "2", Total: "6"},
   {_id : "2", M : "1", S : "0", Total: "1"},
   {_id : "6", M : "1", S : "0", Total: "1"},
   {_id : "3", M : "0", S : "3", Total: "3"}
];

Solution Breakdown

The solution involves three main steps:

1. Extract all unique properties: Find all property keys except '_id' from the objects.

2. Group by _id: Use a map to track objects with the same _id.

3. Merge and sum values: Combine properties and calculate totals for grouped objects.

Complete Implementation

const arr = [
   {_id : "1", S : "2"},
   {_id : "1", M : "4"},
   {_id : "2", M : "1"},
   {_id : "6" , M : "1"},
   {_id : "3", S : "3"}
];

const pickAllConstraints = arr => {
   let constraints = [];
   arr.forEach(el => {
      const keys = Object.keys(el);
      constraints = [...constraints, ...keys];
   });
   return constraints.filter((el, ind) => el !== '_id' && ind === constraints.lastIndexOf(el));
};

const buildItem = (cons, el = {}, prev = {}) => {
   const item = {};
   let total = 0
   cons.forEach(i => {
      item[i] = (+el[i] || 0) + (+prev[i] || 0);
      total += item[i];
   });
   item.total = total;
   return item;
}

const buildCumulativeArray = arr => {
   const constraints = pickAllConstraints(arr);
   const map = {}, res = [];
   arr.forEach(el => {
      const { _id } = el;
      if(map.hasOwnProperty(_id)){
         res[map[_id] - 1] = {
            _id, ...buildItem(constraints, el, res[map[_id] - 1])
         };
      }else{
         map[_id] = res.push({
            _id, ...buildItem(constraints, el)
         });
      }
   });
   return res;
};

console.log(buildCumulativeArray(arr));
[
   { _id: '1', M: 4, S: 2, total: 6 },
   { _id: '2', M: 1, S: 0, total: 1 },
   { _id: '6', M: 1, S: 0, total: 1 },
   { _id: '3', M: 0, S: 3, total: 3 }
]

Alternative Approach Using reduce()

Here's a more concise solution using the reduce() method:

const groupById = (arr) => {
   const grouped = arr.reduce((acc, obj) => {
      const id = obj._id;
      if (!acc[id]) {
         acc[id] = { _id: id, M: 0, S: 0 };
      }
      
      // Add values for M and S properties
      if (obj.M) acc[id].M += parseInt(obj.M);
      if (obj.S) acc[id].S += parseInt(obj.S);
      
      return acc;
   }, {});
   
   // Convert to array and add totals
   return Object.values(grouped).map(item => ({
      ...item,
      total: item.M + item.S
   }));
};

const testArray = [
   {_id : "1", S : "2"},
   {_id : "1", M : "4"},
   {_id : "2", M : "1"},
   {_id : "3", S : "3"}
];

console.log(groupById(testArray));
[
   { _id: '1', M: 4, S: 2, total: 6 },
   { _id: '2', M: 1, S: 0, total: 1 },
   { _id: '3', M: 0, S: 3, total: 3 }
]

How It Works

The solution works by:

1. Creating a constraints array: pickAllConstraints() extracts unique property names (M, S) from all objects.

2. Building items: buildItem() merges values for each constraint and calculates the total.

3. Grouping logic: Uses a map to track existing _id values and their positions in the result array.

Conclusion

This approach efficiently groups objects by _id while summing numeric properties. The solution handles missing properties by defaulting to 0 and provides a total for each grouped object.

Updated on: 2026-03-15T23:19:00+05:30

400 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements