2

I have the following array:

[
     {category: 'Category 1', 'Apr 2021' : 10, 'Mar 2021' : 20, 'Feb 2021': 5},
     {category: 'Category 2', 'Apr 2021' : 8, 'Mar 2021' : 2, 'Feb 2021': 15},
     {category: 'Category 3', 'Apr 2021' : 7, 'Mar 2021' : 1, 'Feb 2021': 5}
]

I would like to add a total row with the sum of categories in the array.

Example:

[
     {category: 'Category 1', 'Apr 2021' : 10, 'Mar 2021' : 20, 'Feb 2021': 5},
     {category: 'Category 2', 'Apr 2021' : 8, 'Mar 2021' : 2, 'Feb 2021': 15},
     {category: 'Category 3', 'Apr 2021' : 7, 'Mar 2021' : 1, 'Feb 2021': 5},
     {category: 'Total',      'Apr 2021' : 25, 'Mar 2021' : 23, 'Feb 2021': 30}
]

I tried looping through all columns using Object.keys. However, it feels like there may be an easier way to achieve this.

What is the best way to calculate the total row?

Please note that "Apr 2021", "Mar 2021" are not fixed so I won't be able to hardcode them.

Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56
developer
  • 1,401
  • 4
  • 28
  • 73
  • Hi, would this work? https://stackoverflow.com/questions/23247859/better-way-to-sum-a-property-value-in-an-array – Tyrcnex Apr 09 '21 at 09:04
  • 1
    Does this answer your question? [Better way to sum a property value in an array](https://stackoverflow.com/questions/23247859/better-way-to-sum-a-property-value-in-an-array) – mert dökümcü Apr 09 '21 at 09:06
  • @mertdökümcü Yes, that is the article I sent, too – Tyrcnex Apr 09 '21 at 09:08

3 Answers3

8

Please note that "Apr 2021", "Mar 2021" are not fixed so I won't be able to hardcode them.

In your case the properties are dynamic. You can try this way with 2 steps:

  1. Using Array#reduce to loop all objects of the array
  2. At each object, you sum the value of each properties by iteration the object due to dynamic property like this
for(const [key, value] of Object.entries(curr)

const array = [
     {category: 'Category 1', 'Apr 2021' : 10, 'Mar 2021' : 20, 'Feb 2021': 5},
     {category: 'Category 2', 'Apr 2021' : 8, 'Mar 2021' : 2, 'Feb 2021': 15},
     {category: 'Category 3', 'Apr 2021' : 7, 'Mar 2021' : 1, 'Feb 2021': 5}
];
const total = array.reduce((acc, curr) => {
  for(const [key, value] of Object.entries(curr)){
    if (key !== 'category') {
      acc[key] ??= 0;
      acc[key] += value;
    }
  }
  
  return acc;
}, {});
console.log([...array, {category: "Total", ...total}]);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56
1
const data = [
     {category: 'Category 1', 'Apr 2021' : 10, 'Mar 2021' : 20, 'Feb 2021': 5},
     {category: 'Category 2', 'Apr 2021' : 8, 'Mar 2021' : 2, 'Feb 2021': 15},
     {category: 'Category 3', 'Apr 2021' : 7, 'Mar 2021' : 1, 'Feb 2021': 5}
];
const res = data.reduce((result, item) => {
  const keys = Object.keys(item);
  keys.forEach(key => {
    if (key === 'category') { return; }
    result[key] = result[key] ? result[key] + item[key] : item[key];
  });
  return result;
}, { category: 'Total' });
data.push(res);
console.log(data);
0

Clean declarative way:

const input = [
     {category: 'Category 1', 'Apr 2021' : 10, 'Mar 2021' : 20, 'Feb 2021': 5},
     {category: 'Category 2', 'Apr 2021' : 8, 'Mar 2021' : 2, 'Feb 2021': 15},
     {category: 'Category 3', 'Apr 2021' : 7, 'Mar 2021' : 1, 'Feb 2021': 5}
]

const totalRow = input.reduce((acc, e) => {
    Object.keys(e)
      .filter(k => k !== 'category')
      .forEach(k => acc[k] ? acc[k] += e[k] : acc[k] = e[k])
    return acc
}, {category: 'Total'})

const res = [...input, totalRow]
console.log(res)
ulou
  • 5,542
  • 5
  • 37
  • 47