Home > Back-end >  Rewriting reduce callback to stop reassigning accumulator
Rewriting reduce callback to stop reassigning accumulator

Time:08-18

I have a function written like so:

 type ChartData = {
    x?: number[],
    y?: number[],
    z?: number[],
  };

  const data = [{ x: 1, y: 2, z: 3 }, { x: 4, y: 7, z: 10 }];

  const formattedData = data.reduce((acc, el) => {
    Object.entries(el!).forEach(([k, v]) => {
      acc = { ...acc, [k]: [...(acc[k as keyof ChartData] || []), v] };
    });

    return acc;
  }, {} as ChartData);

This code does what I want, but I'm getting an eslint error: no-param-reassign.

I know that I could disable the rule, but I wondered if there's a better way of writing this reduce callback so that I am not reassigning acc.

CodePudding user response:

You can assign to acc[k] directly:

const data = [{ x: 1, y: 2, z: 3 }, { x: 4, y: 7, z: 10 }];

const formattedData = data.reduce((acc, el) => {
  Object.entries(el).forEach(([k, v]) => {
    acc[k] = (acc[k] || []).concat(v);
  });
  return acc;
}, {});

console.log(formattedData);

More code but also more efficient (fewer allocations and copies):

const data = [{ x: 1, y: 2, z: 3 }, { x: 4, y: 7, z: 10 }];

const formattedData = data.reduce((acc, el) => {
  Object.entries(el).forEach(([k, v]) => {
    if (!acc[k]) {
      acc[k] = [];
    }
    acc[k].push(v);
  });
  return acc;
}, {});

console.log(formattedData);

CodePudding user response:

This 'no-param-reassign' warning mean that you have modified the function params inside the function. So here maybe a workaround for this warning.

type ChartData = {
  x?: number[],
  y?: number[],
  z?: number[],
};

const data = [{ x: 1, y: 2, z: 3 }, { x: 4, y: 7, z: 10 }];

const formattedData = data.reduce((acc, el) => {
  let newAcc = { ...acc };
  Object.entries(el!).forEach(([k, v]) => {
    newAcc = { ...newAcc , [k]: [...(newAcc [k as keyof ChartData] || []), v] };
  });

  return newAcc ;
}, {} as ChartData);
  • Related