5

Below is a code that adds the amount if the CategoryId is the same and creates a new line item per CategoryId.

self.OriginalLineItems = [
    { CategoryId: 'Cat1', Amount: 15, Type: 'TypeA' },
    { CategoryId: 'Cat1', Amount: 30, Type: 'TypeA' },
    { CategoryId: 'Cat1', Amount: 20, Type: 'TypeB' },
    { CategoryId: 'Cat2', Amount: 10, Type: 'TypeA' },
    { CategoryId: 'Cat2', Amount: 5, Type: 'TypeB' }]

self.newLineItems = [];

self.OriginalLineItems.forEach(function (o) {
    if (!this[o.CategoryId]) {
        this[o.CategoryId] = { CategoryId: o.CategoryId, Amount: 0, Type: o.Type };
        self.newLineItems.push(this[o.CategoryId]);
    }
    this[o.CategoryId].Amount += o.Amount;
}, Object.create(null));

Which would result in the array below:

self.newLineItems = [{ CategoryId: 'Cat1', Amount: 65, Type: 'TypeA' }, 
                     { CategoryId: 'Cat2', Amount: 15, Type: 'TypeA' }]

But I want to add a new condition which is Type, How do I get the results below?

self.newLineItems = [{ CategoryId: 'Cat1', Amount: 45, Type: 'TypeA' }, 
                     { CategoryId: 'Cat1', Amount: 20, Type: 'TypeB' }, 
                     { CategoryId: 'Cat2', Amount: 10, Type: 'TypeA' }, 
                     { CategoryId: 'Cat2', Amount: 5, Type: 'TypeB' }]

I could not find a solution on the linked question.

Len
  • 534
  • 1
  • 15
  • 31

2 Answers2

4

You can use reduce(), findIndex() and every() to do that.

  1. In reduce() set accumulator to [].
  2. Then use findIndex() to find the Object in ac for which all the keys are same.
  3. You need to use every() inside findIndex() to check if all keys which needs to be matched have same value.
  4. If findIndex() returns -1 add the item to ac otherwise increase Amount of item at the index found

let array = [
    { CategoryId: 'Cat1', Amount: 15, Type: 'TypeA' },
    { CategoryId: 'Cat1', Amount: 30, Type: 'TypeA' },
    { CategoryId: 'Cat1', Amount: 20, Type: 'TypeB' },
    { CategoryId: 'Cat2', Amount: 10, Type: 'TypeA' },
    { CategoryId: 'Cat2', Amount: 5, Type: 'TypeB' }]
function addBy(arr,keys){
  return arr.reduce((ac,a) => {
    let ind = ac.findIndex(x => keys.every(k => x[k] === a[k]));
    ind === -1 ? ac.push(a) : ac[ind].Amount += a.Amount;
    return ac;
  },[])
}
console.log(addBy(array,["CategoryId","Type"]));
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
3

You can make the key (in your loop) for your object like so:

const key = JSON.stringify([o.CategoryId, o.Type]);

Then replace this[o.CategoryId] with this[key]. That's it.

trincot
  • 317,000
  • 35
  • 244
  • 286