Dan
Dan

Reputation: 817

Why does my reduce accumulator reset?

How do I retain the accumulative value of my reduce function? Each iteration resets the object value.

const a = [1, 2, 3, 4, 5];

const b = {
  1: {
    name: 'Dan',
    age: 25
  },
  2: {
    name: 'Peter',
    age: 28
  },
  3: {
    name: 'Mark',
    age: 38
  },
  4: {
    name: 'Larry',
    age: 32
  },
  5: {
    name: 'Simon',
    age: 25
  },
}

const f = a.reduce((acc, val) => {
  console.log({
    acc
  })
  return {
    [val]: {
      age: b[val].age
    }
  }
}, {})

console.log(f); // 5: {age: 25}

My desired outcome would be:

{
  1: { age: 25 },
  2: { age: 28 },
  3: { age: 38 },
  4: { age: 32 },
  5: { age: 25 },
}

(This example is a demo)

Upvotes: 5

Views: 1309

Answers (3)

Bryan Lee
Bryan Lee

Reputation: 1107

Your reduce accumulator can also reset if you happen to have an if else statement in your reduce function, whereby you return an accumulator for the if statement but forget to handle the else statement and do not return an accumulator - in that case when the else statement is triggered no accumulator is returned and the accumulator becomes undefined.

For example this works:

let reducedArray = array.reduce((acc, curr) => {
          if (
            curr[
              property_name
            ]
          ) {
            return {
              ...acc,
              ...{
                [curr.id]:
                  (acc[curr.id] ?? 0) +
                  curr[
                    property_name
                  ]!
              },
            };
          } else {
            return acc;
          }
        }, {} as { [key: string]: number });

But this will not work:

let reducedArray = array.reduce((acc, curr) => {
          if (
            curr[
              property_name
            ]
          ) {
            return {
              ...acc,
              ...{
                [curr.id]:
                  (acc[curr.id] ?? 0) +
                  curr[
                    property_name
                  ]!
              },
            };
          }
        }, {} as { [key: string]: number });

Upvotes: 0

Narendra Jadhav
Narendra Jadhav

Reputation: 10262

As per MDN

The reduce() method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.

On each iteration you return new object inside of reduce() function and you are not storing previous value of that accumulator. So you need to be merge or assign previous value with new value.

One way you can use Object.assign() method to get the required result.

DEMO

const a = [1, 2, 3, 4, 5];

const b = {1: {name: 'Dan',age: 25},2: {name: 'Peter',age: 28},3: {name: 'Mark',age: 38},4: {name: 'Larry',age: 32},5: {name: 'Simon',age: 25}}

let result = a.reduce((acc, val) => Object.assign(acc,{[val]: {age:b[val].age}}), {});

console.log(result);
.as-console-wrapper {max-height: 100% !important;top: 0;}

second way you can do like this obje[val]=newValue and return accumulator.

DEMO

const a = [1, 2, 3, 4, 5];

const b = {1: {name: 'Dan',age: 25},2: {name: 'Peter',age: 28},3: {name: 'Mark',age: 38},4: {name: 'Larry',age: 32},5: {name: 'Simon',age: 25}}

let result = a.reduce((acc, val) =>{
acc[val]= {age:b[val].age};
return acc;
}, {});

console.log(result);
.as-console-wrapper {max-height: 100% !important;top: 0;}

Another way you can combine using the spread syntax

DEMO

const a = [1, 2, 3, 4, 5];

const b = {1: {name: 'Dan',age: 25},2: {name: 'Peter',age: 28},3: {name: 'Mark',age: 38},4: {name: 'Larry',age: 32},5: {name: 'Simon',age: 25}}

let result = a.reduce((acc, val) => {
return {...acc,...{[val]:{age:b[val].age}}}
}, {});

console.log(result);
.as-console-wrapper {max-height: 100% !important;top: 0;}

Upvotes: 1

Ori Drori
Ori Drori

Reputation: 191976

Add the previous accumulator to the returned value using object spread (like this example) or Object.assign():

const a = [1, 2, 3, 4, 5];

const b = {"1":{"name":"Dan","age":25},"2":{"name":"Peter","age":28},"3":{"name":"Mark","age":38},"4":{"name":"Larry","age":32},"5":{"name":"Simon","age":25}};

const f = a.reduce((acc, val) => ({
  ...acc, // previous accumulator
  [val]: {
    age: b[val].age
  }
}), {})

console.log(f); // 5: {age: 25}

Upvotes: 6

Related Questions