ECMAScript - Grouping arrays using Object.groupBy and Map.groupBy

As JavaScript, being one of the most dynamic and widely-used programming languages, constantly evolves to meet the needs of developers.

JavaScript has introducd Object.groupBy and Map.groupBy for grouping data in the latest proposal that has reached stage 4,

Before

Prior to the introduction of Object.groupBy() in JavaScript, array elements were normally grouped using a combination of Array.reduce() and other array manipulation techniques. Here is an example of how we can organize the timesheetEntries array based on the ‘project’ property:

const timesheetEntries = [
  {
    date: '2024-01-08',
    startTime: '09:00 AM',
    endTime: '05:00 PM',
    project: 'Miru',
    description: 'Worked adding a new feature'
  },
  {
    date: '2024-01-09',
    startTime: '10:30 AM',
    endTime: '04:45 PM',
    project: 'Miru',
    description: 'Implemented Google analytics'
  },
  {
    date: '2024-01-10',
    startTime: '08:15 AM',
    endTime: '12:00 PM',
    project: 'Blogs',
    description: 'Written a blog'
  },
];

// Grouping by 'project' property using reduce
const groupedByProject = timesheetEntries.reduce((acc, entry) => {
  const key = entry.project;

  if (!acc[key]) {
    acc[key] = [];
  }

  acc[key].push(entry);
  return acc;
}, {});

console.log(groupedByProject);
// Output

{
  "Miru": [
    {
        "date": "2024-01-08",
        "startTime": "09:00 AM",
        "endTime": "05:00 PM",
        "project": "Miru",
        "description": "Worked adding a new feature"
    },
    {
        "date": "2024-01-09",
        "startTime": "10:30 AM",
        "endTime": "04:45 PM",
        "project": "Miru",
        "description": "Implemented Google analytics"
    }
  ],
  "Blogs": [
    {
        "date": "2024-01-10",
        "startTime": "08:15 AM",
        "endTime": "12:00 PM",
        "project": "Blogs",
        "description": "Written a blog"
    }
  ]
}

Object.groupBy

The Object.groupBy method efficiently groups items based on an arbitrary key. As demonstrated in the below example, we can effortlessly group elements by applying a custom logic, such as odd/even numbers. The result is a null-prototype object, enhancing destructuring and preventing accidental collisions with global Object properties.

  const timesheetEntries = [
  {
    date: '2024-01-08',
    startTime: '09:00 AM',
    endTime: '05:00 PM',
    project: 'Miru',
    description: 'Worked adding a new feature'
  },
  {
    date: '2024-01-09',
    startTime: '10:30 AM',
    endTime: '04:45 PM',
    project: 'Miru',
    description: 'Implemented Google analytics'
  },
  {
    date: '2024-01-10',
    startTime: '08:15 AM',
    endTime: '12:00 PM',
    project: 'Blogs',
    description: 'Written a blog'
  },
];

const groupedObject = Object.groupBy(timesheetEntries, (entries, index) => {
  return entries.project;
});

console.log(groupedObject)
// Output

{
  "Miru": [
    {
      "date": "2024-01-08",
      "startTime": "09:00 AM",
      "endTime": "05:00 PM",
      "project": "Miru",
      "description": "Worked adding a new feature"
    },
    {
      "date": "2024-01-09",
      "startTime": "10:30 AM",
      "endTime": "04:45 PM",
      "project": "Miru",
      "description": "Implemented Google analytics"
    }
  ],
  "Blogs": [
    {
      "date": "2024-01-10",
      "startTime": "08:15 AM",
      "endTime": "12:00 PM",
      "project": "Blogs",
      "description": "Written a blog"
    }
  ]
}

Map.groupBy:

Map.groupBy returns items in a Map, providing a more versatile approach for grouping using object keys. This is particularly useful for scenarios involving complex key types, such as compound keys or tuples.

  const timesheetEntries = [
  {
    date: '2024-01-08', startTime: '09:00 AM', endTime: '05:00 PM',
    project: 'Miru', description: 'Worked adding a new feature'
  },
  {
    date: '2024-01-09',
    startTime: '10:30 AM',
    endTime: '04:45 PM',
    project: 'Miru',
    description: 'Implemented Google analytics'
  },
  {
    date: '2024-01-10',
    startTime: '08:15 AM',
    endTime: '12:00 PM',
    project: 'Blogs',
    description: 'Written a blog'
  },
];

function calculateHoursWorked(startTime, endTime) {
  const start = new Date(`2000-01-01 ${startTime}`);
  const end = new Date(`2000-01-01 ${endTime}`);

  // Calculate the time difference in milliseconds
  const timeDiff = end - start;

  // Convert the time difference to hours
  const hoursWorked = timeDiff / (1000 * 60 * 60);

  return hoursWorked;
}

const longHours = {longHours: true}
const shortHours = {shortHours: true}

const groupedTimesheetMap = Map.groupBy(timesheetEntries, entry => {
  const hoursWorked = calculateHoursWorked(entry.startTime, entry.endTime);
  return hoursWorked >= 7 ? longHours : shortHours;
});

console.log(groupedTimesheetMap)
// Output:

new Map([
  [
    {
      "longHours": true
    },
    [
      {
        "date": "2024-01-08",
        "startTime": "09:00 AM",
        "endTime": "05:00 PM",
        "project": "Miru",
        "description": "Worked adding a new feature"
      }
    ]
  ],
  [
    {
      "shortHours": true
    },
    [
      {
        "date": "2024-01-09",
        "startTime": "10:30 AM",
        "endTime": "04:45 PM",
        "project": "Miru",
        "description": "Implemented Google analytics"
      },
      {
        "date": "2024-01-10",
        "startTime": "08:15 AM",
        "endTime": "12:00 PM",
        "project": "Blogs",
        "description": "Written a blog"
      }
    ]
  ]
])

Need help on your Ruby on Rails or React project?

Join Our Newsletter