0

I have an array like this:

const inputArray = [
 {
 userId: 1,
 sum: 30,
 },
 {
 userId: 1,
 sum: 20,
 },
 {
 userId: 2,
 sum: 50,
 },
 {
 userId: 2,
 sum: 80,
 },
];

Then I wrote a function that sums the values ​​by key and got the following result:

const output = [
 {
 userId: 1,
 sum: 50,
 },
 50,
 {
 userId: 2,
 sum: 130,
 },
 130,
];

How can this error be corrected? Function code below:

const output = inputArray.reduce((accumulator, currentItem) => {
 const index = accumulator.findIndex((item) => item.userId === currentItem.userId);
 if (index < 0) {
 return [...accumulator, currentItem];
 } else {
 return [...accumulator, (accumulator[index].sum += currentItem.sum)];
 }
}, []);
asked Dec 3, 2021 at 11:07
4
  • What is the expected result? Commented Dec 3, 2021 at 11:10
  • @VLAZ I think he just want the same array with the sum property incremented Commented Dec 3, 2021 at 11:11
  • @Nick and I think it would be good to include all relevant information in the question itself. Commented Dec 3, 2021 at 11:11
  • Write that so... Commented Dec 3, 2021 at 11:12

3 Answers 3

1

I would suggest, instead of finding index as it can be costly iterating array again and again, you can simply make an object with userId as key and sum as value.

After that, u can do Object.entries(inputObj) to make and array of object out of this.

var inputArray = [{ userId: 1,sum: 30},{userId: 1,sum: 20},{userId: 2,sum: 50},{userId: 2,sum: 80}];
var outputObj = inputArray.reduce((finalObj, curObj) => {
 if (!finalObj[curObj.userId]) finalObj[curObj.userId] = curObj.sum //<--- adding new user if do not exist in the object
 else finalObj[curObj.userId] += curObj.sum; // <---- if already present, the add the sum
 return finalObj;
}, {})
var output = Object.entries(outputObj).map((obj) => ({
 userId: obj[0], //<--- key of object as userId
 sum: obj[1] //<--- value of object as sum
}));
console.log(output)

answered Dec 3, 2021 at 11:17
Sign up to request clarification or add additional context in comments.

Comments

0

Try

const inputArray = [
 {
 userId: 1,
 sum: 30,
 },
 {
 userId: 1,
 sum: 20,
 },
 {
 userId: 2,
 sum: 50,
 },
 {
 userId: 2,
 sum: 80,
 },
];
const output = inputArray.reduce((accumulator, currentItem) => {
 const matchedItem = accumulator.find((item) => item.userId === currentItem.userId);
 if (!matchedItem) {
 return [...accumulator, currentItem];
 } else {
 matchedItem.sum += currentItem.sum
 return accumulator
 }
}, []);
console.log(output)

you were appending a new item to accumulator even when the item already existed, you just needed to mutate it. Also, since you dealing with an array of objects, you can use find as it will return a reference to the matched object itself, letting you update the object directly, rather than having to use findIndex then use the index to find it in the array again

answered Dec 3, 2021 at 11:16

2 Comments

Yes, it works, but this way mutates the original array
so whats the problem with mutating the array?
0

You can try this:

const inputArray = [
 {
 userId: 1,
 sum: 30,
 },
 {
 userId: 1,
 sum: 20,
 },
 {
 userId: 2,
 sum: 50,
 },
 {
 userId: 2,
 sum: 80,
 },
];
const res = Array.from(inputArray.reduce((m, {userId, sum}) => m.set(userId, (m.get(userId) || 0) + sum), new Map), ([userId, sum]) => ({userId, sum}));
answered Dec 3, 2021 at 11:27

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.