0

Suppose I have:

const arr = [
    {'name': 'P1','value': 150, 'nn': 2},
    {'name': 'P1','value': 150, 'nn': 3},
    {'name': 'P2','value': 200, 'nn': 5},
    {'name': 'P3','value': 450, 'nn': 1}
]
const keysToSum = ['value', 'nn' ]

and I want:

[
  { name: 'P1', value: 300, nn: 5 },
  { name: 'P2', value: 200, nn: 5 },
  { name: 'P3', value: 450, nn: 1 }
]

So I want to sum the values inside the keys value and nn (because these keys are in keysToSum) if name is the same. How can I do that?

I know I can use reduce, for example:

const result = arr.reduce((acc, val) => {
    const o = acc.filter((obj) => {
        return obj.name == val.name;
    }).pop() || {name: val.name, value: 0};
    
    o.value += val.value;
    acc.push(o);
    return acc;
},[])

But this piece of code works with only a key (value in that case), how can generalize it using keysToSum?

const arr = [
{'name': 'P1','value': 150, 'nn': 2},
{'name': 'P1','value': 150, 'nn': 3},
{'name': 'P2','value': 200, 'nn': 5},
{'name': 'P3','value': 450, 'nn': 1}
];

const result = arr.reduce((acc, val) => {
    const o = acc.filter((obj) => {
        return obj.name == val.name;
    }).pop() || {name: val.name, value: 0};
    
    o.value += val.value;
    acc.push(o);
    return acc;
},[]);

console.log(result)

4
  • 1
    How is nn equal to 5? 0 + 3 = 5? 2 = 5? Commented Sep 17, 2020 at 13:48
  • I think the example is wrong. P1 should be 3, and P2 should be 2. Commented Sep 17, 2020 at 13:49
  • @epascarello yes, sorry. I edited the main message Commented Sep 17, 2020 at 13:51
  • You don't need to use filter(). Let the callback of .reduce() return an object and use the value of name as a key in it. Commented Sep 17, 2020 at 13:52

2 Answers 2

1

Using reduce with an object that uses the name as a key, you can easily keep track of the objecs with dupe and increment the properties.

const arr = [
    {'name': 'P1','value': 150, 'nn': 0},
    {'name': 'P1','value': 150, 'nn': 3},
    {'name': 'P2','value': 200, 'nn': 2},
    {'name': 'P3','value': 450, 'nn': 5}
]
const keysToSum = ['value', 'nn' ]

const summed = Object.values(arr.reduce((obj, record) => {
  // have we seen this name yet? If not copy the record
  if (!obj[record.name]) {
    obj[record.name] = { ...record };
  } else {
    // if we saw it, sum the fields we care about
    keysToSum.forEach(key => {
      obj[record.name][key] += record[key];
    })
  }
  return obj
}, {}));

console.log(summed)

Sign up to request clarification or add additional context in comments.

Comments

1

You could reduce the array by using an object and iterate the wanted keys for summing property values.

const
    array = [{ name: 'P1', value: 150, nn: 0 }, { name: 'P1', value: 150, nn: 3 }, { name: 'P2', value: 200, nn: 2 }, { name: 'P3', value: 450, nn: 5 }],
    keysToSum = ['value', 'nn'],
    result = Object.values(array.reduce((r, { name, ...o }) => {
        if (!r[name]) r[name] = { name };
        keysToSum.forEach(k => r[name][k] = (r[name][k] || 0) + o[k]);
        return r;
    }, []));

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

Comments

Your Answer

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.