0

The problem was:

const arr = [
  { name1: 'value1', qty: 1, time: 1 },
  { name1: 'value2', qty: 1, time: 2 },
];

// using this reducer works!
const reducer = (acc, { name1, qty}) => {
  const newQty = parseInt(acc[name1] ?? 0) + parseInt(qty); //?
  return {
    ...acc,
    [name1]: newQty
  };
};


arr.reduce(reducer, {})
// this returns: {value1: sum, value2: sum, ... }

So far so good... but what happens when you have this?

const arr2 = [
  { name2: 'valueX', qty: 1, time: 1},
  { name2: 'valueY', qty: 1, time: 2},
];

Copy pasting and then changing the name works fine, of course... but is there another way?

Noriller
  • 342
  • 1
  • 4
  • 12
  • [How much research effort is expected of Stack Overflow users?](https://meta.stackoverflow.com/questions/261592/how-much-research-effort-is-expected-of-stack-overflow-users) – Andreas May 15 '21 at 13:46
  • @Andreas I actually wanted to share my own answer, but for some reason it makes me wait to do so... – Noriller May 16 '21 at 14:12
  • You did, but that doesn't relieves you from [research, research and more research](https://meta.stackoverflow.com/questions/261592/how-much-research-effort-is-expected-of-stack-overflow-users). And only then, when you haven't found anything for that specific problem, add a question and, if already available, an answer. And how to group an array of objects is asked at least once a day... – Andreas May 16 '21 at 15:23

2 Answers2

0

It turns out there is:

const reducer = (acc, { time, qty, ...rest }) => {
  const name = Object.values(rest);
  const newQty = parseInt(acc[name] ?? 0) + parseInt(qty);
  return {
    ...acc,
    [name]: newQty
  };
};

This will work fine as long all objects you need to reduce have that format.

(I didn't test adding non existent keys, but probably would still work...)

All you need to do is to "remove" by expliciting all the keys that are "common" and using the spreading operator to catch the changing one.

Noriller
  • 342
  • 1
  • 4
  • 12
0

It really depends on your specific use case, but you can create a function that generates the correct reducer, taking the key as input:

const arr = [
  { name1: 'value1', qty: 1, time: 1 },
  { name1: 'value2', qty: 1, time: 2 },
];

// using this reducer works!
const makeReducer = key => (acc, cur) => {
  const newQty = parseInt(acc[key] ?? 0) + parseInt(cur.qty); 
  return {
    ...acc,
    [cur[key]]: newQty
  };
};

console.log(arr.reduce(makeReducer('name1'), {}))

const arr2 = [
  { name2: 'valueX', qty: 1, time: 1},
  { name2: 'valueY', qty: 1, time: 2},
];
console.log(arr2.reduce(makeReducer('name2'), {}))
bel3atar
  • 913
  • 4
  • 6