Villemh
Villemh

Reputation: 197

How to sum up object values in array by some key?

I cannot find solution to this problem.

I have array:

const taxItems = [{
    taxCode: '430',
    taxAmount: 2,
    ItemTaxPercentage: 20,
    taxCategory: '2'
  },
  {
    taxCode: '430',
    taxAmount: 4,
    ItemTaxPercentage: 20,
    taxCategory: '2'
  },
  {
    taxCode: '431',
    taxAmount: 5,
    ItemTaxPercentage: 20,
    taxCategory: '2'
  },
  {
    taxCode: '430',
    taxAmount: 6,
    ItemTaxPercentage: 20,
    taxCategory: '2'
  }
]

And from this array I want to sum up all objects by taxCode.I want to have results like this:

var results = [{
    taxCode: '430',
    taxAmount: 12,
    ItemTaxPercentage: 20,
    taxCategory: '2'
  },
  {
    taxCode: '431',
    taxAmount: 5,
    ItemTaxPercentage: 20,
    taxCategory: '2'
  }
]

I tried to use lodash:

var results =
lodash(taxItems)
  .groupBy('taxCode')
  .map((objs, key) => ({
      'taxCode': key,
      'taxAmount': lodash.sumBy(objs, 'taxAmount') }))
  .value();

But it only works with key value pair. I will loose the original structure of the object.

What would be the correct solution to my problem?

Upvotes: 0

Views: 121

Answers (4)

Akrion
Akrion

Reputation: 18515

You could also solve this via _.map, _.groupBy and _.mergeWith:

const taxItems = [{ taxCode: '430', taxAmount: 2, ItemTaxPercentage: 20, taxCategory: '2' }, { taxCode: '430', taxAmount: 4, ItemTaxPercentage: 20, taxCategory: '2' }, { taxCode: '431', taxAmount: 5, ItemTaxPercentage: 20, taxCategory: '2' }, { taxCode: '430', taxAmount: 6, ItemTaxPercentage: 20, taxCategory: '2' } ]

const result = _.map(_.groupBy(taxItems, 'taxCode'), x => 
  _.mergeWith(...x, (o,s,k) => k == 'taxAmount' ? o+s : s))

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

Upvotes: 0

Sankha Karunasekara
Sankha Karunasekara

Reputation: 1726

This will work. with a simple reduce. you don't need to use lodash for this.

const results = taxItems.reduce(function(sum, taxItem) {

    let index = sum.map(item => item.taxCode).indexOf(taxItem.taxCode);
    if (index == -1) {
        sum.push(taxItem);
    } else {
        sum[index].taxAmount = sum[index].taxAmount + taxItem.taxAmount;
    }

    return sum;
}, []);

//results 
//[{"taxCode":"430","taxAmount":12,"ItemTaxPercentage":20,"taxCategory":"2"}{"taxCode":"431","taxAmount":5,"ItemTaxPercentage":20,"taxCategory":"2"}]

Upvotes: 0

Code Maniac
Code Maniac

Reputation: 37755

With simple reduce you can do it this way.

const taxItems = [{
    taxCode: '430',
    taxAmount: 2,
    ItemTaxPercentage: 20,
    taxCategory: '2'
  },
  {
    taxCode: '430',
    taxAmount: 4,
    ItemTaxPercentage: 20,
    taxCategory: '2'
  },
  {
    taxCode: '431',
    taxAmount: 5,
    ItemTaxPercentage: 20,
    taxCategory: '2'
  },
  {
    taxCode: '430',
    taxAmount: 6,
    ItemTaxPercentage: 20,
    taxCategory: '2'
  }
]

let op = Object.values(taxItems.reduce((op,cur)=>{
  if(op[cur['taxCode']]){
    op[cur['taxCode']]['taxAmount']+= cur['taxAmount'];
  } else {
    op[cur['taxCode']] = cur
  }
  return op;
},{}))

console.log(op)

Upvotes: 0

Ori Drori
Ori Drori

Reputation: 191936

Spread the 1st object of each group into the result object, to get the recurring properties:

const taxItems = [{"taxCode":"430","taxAmount":2,"ItemTaxPercentage":20,"taxCategory":"2"},{"taxCode":"430","taxAmount":4,"ItemTaxPercentage":20,"taxCategory":"2"},{"taxCode":"431","taxAmount":5,"ItemTaxPercentage":20,"taxCategory":"2"},{"taxCode":"430","taxAmount":6,"ItemTaxPercentage":20,"taxCategory":"2"}];

const results = _(taxItems)
  .groupBy('taxCode')
  .map((objs, taxCode) => ({
      ..._.head(objs),
      taxCode,
      taxAmount: _.sumBy(objs, 'taxAmount') }))
  .value();
  
console.log(results);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Upvotes: 1

Related Questions