Home > front end >  Reduce method not return the same result when process the same array
Reduce method not return the same result when process the same array

Time:11-07

This question is come from enter image description here

However,if I ran them together,the seconds result(from result3) is not as expected(enter image description here

I do not know why this happen,can anyone help me to analysis this?

Also,I want to know if there are a more elegant one-liner solution to do it.

Thanks in advance!

CodePudding user response:

Your version mutates, as has been pointed out. It mutates the objects that are in the data array. So if you use the data array after your let result2 = then the data array has been mutated.

If your fiddle looked like:

let result3 = data.reduce(...);
console.log(result3);

let result2 = data.reduce(...);
console.log(result2);

then the answers will be the same values, because the data array doesn't get mutated until your result2 code runs. But any other users of the data array, in the future, would have to deal with the mutated values.

Meanwhile, you can either do what has been recommended in the comments and shallow copy:

let result2 = data.reduce((a, v) => {
  let obj = a.find(i => i.id == v.id);
  if (obj) {
      obj.number  = v.number;
  } else {
      const copy = { ...v }; // <-- don't mutate the original
      a.push(copy);
  }
  return a;
}, [])

Another simple way of doing this (exact data set) is to rebuild the data after the fact.

const dictionary = data.reduce((dict, { id, number }) => {
  const sum = number   dict[id] ?? 0;
  dict[id] = sum;
  return dict;
}, {});

const results = Object.entries(dictionary)
  .map(([id, number]) => ({ id, number }));

CodePudding user response:

As hinted by @Jaromanda X's comment, since you don't want elements of your original array mutated, you need to do a deep copy of the obj object because, the find array method returns a shallow references. You have many options discussed here. The more terse one would be:

...
let result2 = data.reduce((a, v) => {
  let obj = [...a.find(i => i.id == v.id)];
...

CodePudding user response:

Another way to archive it is to utilize the Map data structure in js

const result = Array.from(
  data.reduce(
    (acc, next) => acc.set(next.id, next.number   acc.get(next.id) || 0),
    new Map(),
  ),
  ([id, number]) => ({ id, number }),
);
console.log(result)
  • Related