I have a 2D array:
[ [ 1, 2, 43, 5 ],
[ 1, 5, 12, 1 ],
[ 2, 3, 6, 77 ],
[ 2, 1, 48, 94 ],
[ 3, 3, 15, 85 ],
[ 3, 7, 97, 86 ],
[ 4, 0, 9, 54 ],
[ 4, 1, 83, 16 ]]
This is the result I'm after:
[ [ 1, 7, 55, 6 ],
[ 2, 4, 54, 171 ],
[ 3, 10, 112, 171 ],
[ 4, 1, 92, 70 ]]
Match the first index within each array, and sum the other indexes.
My first thought was to use reduce and findIndex to find the index of the first item, add item to array if not found, otherwise sum the values.
But I really don't know what I'm doing.
array.reduce((acc,e) =>
{ let index = acc.findIndex(inner => inner[0] === e[0]);
(index === -1) ? [...acc,e] : (acc[index][1] += e[1]) && (acc[index][2] += e[2]) && (acc[index][3] += e[3]);
return acc},[]);
Help please!
EDIT: I'm learning! A simple change to my attempt and it worked, thanks for pointing out my error @mykaf and @trincot.
Change made to update accumulator [...acc,e] to acc.push(e)
const input = [ [ 1, 2, 43, 5 ],
[ 1, 5, 12, 1 ],
[ 2, 3, 6, 77 ],
[ 2, 1, 48, 94 ],
[ 3, 3, 15, 85 ],
[ 3, 7, 97, 86 ],
[ 4, 0, 9, 54 ],
[ 4, 1, 83, 16 ]];
const result = input.reduce((acc,e) =>
{ let index = acc.findIndex(inner => inner[0] === e[0]);
(index === -1) ? acc.push(e) : (acc[index][1] += e[1]) && (acc[index][2] += e[2]) && (acc[index][3] += e[3]);
return acc;
},[]);
console.log(result);
Read on for some excellent/better answers to the problem.
Using
reduceis a good way to do it, but in your attempt you never update the accumulatoracc: the callback always returns the same, unmutatedaccarray.I would however suggest using a
Mapor a plain object as your accumulator, so that you don't need to scan an array withfindIndex, but can immediately look up by key. Then when the reducing is complete, you can extract the values from the result.Here is how that would work:
If you want to optimize for speed, then you're better off with plain old
forloops, and to support any data type for the key column, you would use aMap:This faster version mutates the input array. If you don't want that, you'll need to spend some processing time to create a new sub array by doing a spread like
acc.set(key, [...arr[i]]);