-1

So I have this array of objects which I need to reduce based on each object's prop value as well as count the total.

What I mean to say is, suppose I have this array of objects:

[
     { dateTime: '2021-07-30', count: 4 },
     { dateTime: '2021-07-31', count: 1 },
     { dateTime: '2021-08-01', count: 2 },
     { dateTime: '2021-08-02', count: 1 },
     { dateTime: '2021-08-03', count: 2 },
     { dateTime: '2021-08-04', count: 3 }
]

I want to reduce it to something like this:

[
     { month: '2021-07', count: 5 },
     { month: '2021-08', count: 8 }
]

Here's the snippet:

const data = [{
    dateTime: '2021-07-30',
    count: 4
  },
  {
    dateTime: '2021-07-31',
    count: 1
  },
  {
    dateTime: '2021-08-01',
    count: 2
  },
  {
    dateTime: '2021-08-02',
    count: 1
  },
  {
    dateTime: '2021-08-03',
    count: 2
  },
  {
    dateTime: '2021-08-04',
    count: 3
  }
];

const stackedMonths = data.reduce((acc, curr) => {

  return [{
    month: curr.dateTime.slice(0, 7),
    count: acc + curr.count
  }];

}, []);

console.log(stackedMonths);

After trying the code, I'm getting this which doesn't make any sense:

[ { month: '2021-08', count: '[object Object]2' } ]

What am I doing wrong here? Please note that I'm new to reduce and I'm still learning it.

5
  • 1
    On this line, count: acc + curr.count, acc is an object. When you concatenate an object with a number, you get a string (unless you have a toValue method on the object that returns a number.) Surely you didn't intend to concatenate an object with a number? Commented Aug 25, 2021 at 17:53
  • No I did not. I was trying it out myself from various answers here in SO. But isn't acc an array? Commented Aug 25, 2021 at 17:55
  • 1
    An Array is an Object. You can't add numbers to an Object itself, as an Object isn't a Number (or any form of a Number). Commented Aug 25, 2021 at 17:57
  • @esqew Understood. Thanks Commented Aug 25, 2021 at 17:57
  • 1
    It should be an array, but if it was, you wouldn't get [object Object]2. Yes, arrays are objects, but arrays have a different outcome when concatenating in this way Commented Aug 25, 2021 at 17:58

1 Answer 1

2

You can use Array#reduce with an object to store the sum for each month.

const arr = [
     { dateTime: '2021-07-30', count: 4 },
     { dateTime: '2021-07-31', count: 1 },
     { dateTime: '2021-08-01', count: 2 },
     { dateTime: '2021-08-02', count: 1 },
     { dateTime: '2021-08-03', count: 2 },
     { dateTime: '2021-08-04', count: 3 }
];
const res = Object.values(arr.reduce((acc, curr)=>{
  const month = curr.dateTime.slice(0, -3);
  (acc[month] ??= {month, count: 0}).count += curr.count;
  return acc;
}, {}));
console.log(res);

If the value of month does not yet exist as a key on the accumulator, it is set to {month: month, count: 0}. Then, the count is incremented by the current object's count.

Sign up to request clarification or add additional context in comments.

6 Comments

Hi. Can you please explain this part (acc[month] ??= {month, count: 0}).count += curr.count;?
@s.khan If the value of month does not yet exist as a key on the accumulator, it is set to {month: month, count: 0}. Then, the count is incremented by the current object's count.
Very clever use of Object.values and ??=, love the succinctness.
@Unmitigated hey man, I'm getting an error in NodeJS because of ??= operator.
@s.khan You can replace that with acc[month] = acc[month] || {month, count: 0}.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.