Group an array of objects and add the time attribute

Viewed 69

I have an array of custom objects which is populated with user inputs. The array looks like this:

let array = [
  {Course: "Design", Hours: "01:00:00", Week: "1"}, 
  {Course: "Design", Hours: "01:00:00", Week: "3"}, 
  {Course: "Design", Hours: "01:00:00", Week: "2"}, 
  {Course: "Design", Hours: "01:00:00", Week: "1"}, 
  {Course: "Design", Hours: "01:00:00", Week: "2"}
]

I need to modify this array so all hours from the same week will be calculated, and the values will be placed in the array according to the order of the weeks. My desired result would be like this:

let newArray = [
  {Course: "Design", Hours: "02:00:00", Week: "1"}, 
  {Course: "Design", Hours: "02:00:00", Week: "2"},
  {Course: "Design", Hours: "01:00:00", Week: "3"},  
]

So basically I need to sort and calculate the sum at the same time.

1 Answers

You can use moment.js to get the sum of the time strings.

To group the items by week, you can use .reduce.

Finally, to sort the items by Week, use .sort:

let array = [
  {Course: "Design", Hours: "01:00:00", Week: "1"}, 
  {Course: "Design", Hours: "01:00:00", Week: "3"}, 
  {Course: "Design", Hours: "01:00:00", Week: "2"}, 
  {Course: "Design", Hours: "01:00:00", Week: "1"}, 
  {Course: "Design", Hours: "01:00:00", Week: "2"}
];

const addTwoTimeStrs = (a, b) => {
  let sum = moment.duration(a).add(moment.duration(b));
  sum = moment.utc(sum.asMilliseconds()).format("HH:mm:ss");
  return sum;
}

const arr = Object.values(
  array.reduce((acc,item) => {
    const { Hours: hours, Week: week } = item;
    const weekItem = acc[week];
    acc[week] = weekItem
      ? { ...weekItem, Hours: addTwoTimeStrs(weekItem.Hours,hours) }
      : item;
    return acc;
  }, {})
);

const res = arr.sort((a,b) => Number(a.Week) - Number(b.Week));

console.log(res.map(e => e.Hours));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous"></script>

Related