2

Let's say I have an array of objects:

[
    {
        category: 'Category A',
        mainUnits: 5,
        subUnits: 3
    },

    {
        category: 'Category A',
        mainUnits: 9,
        subUnits, 12
    },

    {
        category: 'Category B',
        mainUnits: 4,
        subUnits, 6
    },

    {
        category: 'Category B',
        mainUnits: 2,
        subUnits, 4
    }
]

However, I can't seem to get an array that looks like this:

[
    {
        category: 'Category A',
        mainUnits: 14,
        subUnits: 15
    },

    {
        category: 'Category B',
        mainUnits: 6,
        subUnits: 10
    }
]

I have been able to make some sort of headway, but can't quite get the exact result I need. Any guidance is greatly appreciated, thanks!

3 Answers 3

6

The .reduce array method seems like a good fit here.

Use the array .find method to see if there is already an item with that category in the result. If so, add the fields, but if not, add the item to the result:

const input = [{
  category: 'Category A',
  mainUnits: 5,
  subUnits: 3
}, {
  category: 'Category A',
  mainUnits: 9,
  subUnits: 12,
}, {
  category: 'Category B',
  mainUnits: 4,
  subUnits: 6,
}, {
  category: 'Category B',
  mainUnits: 2,
  subUnits: 4,
}];

const result = input.reduce((result, item) => {
  const existing = result.find(x => x.category === item.category);
  if (existing) {
    existing.mainUnits += item.mainUnits;
    existing.subUnits += item.subUnits;
  } else {
    result.push(item);
  }

  return result;
}, []);

console.log(result);

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

2 Comments

thank you SO much!! I was in that direction, and I think I overcomplicated it, because this is nice and simple, and my version was so convoluted, missing the main logic. Thanks so much!!
I have the same problem, but in my case each item in the input has an id and other unique data that I want to ignore in the final result. My output is coming out as only having the first instance of each "category".
4

@CRice's answer is great, but here's another approach if you'd like:

const input = [{
  category: 'Category A',
  mainUnits: 5,
  subUnits: 3
}, {
  category: 'Category A',
  mainUnits: 9,
  subUnits: 12
}, {
  category: 'Category B',
  mainUnits: 4,
  subUnits: 6
}, {
  category: 'Category B',
  mainUnits: 2,
  subUnits: 4
}];

let sums = {};
for (let entry of input) {
  sums[entry.category] = sums[entry.category] || {
    mainUnits: 0,
    subUnits: 0
  };
  sums[entry.category].mainUnits += entry.mainUnits;
  sums[entry.category].subUnits += entry.subUnits;
}

const result = Object.keys(sums).map(category => Object.assign({
  category
}, sums[category]));

console.log(result);

Comments

0

You need a function like this:

function catTotals(catsArray){
  var cats = [], totals = [];
  for(var i=0,ca,c,o,x,l=catsArray.length; i<l; i++){
    ca = catsArray[i]; c = ca.category; x = cats.indexOf(c);
    if(x === -1){
      cats.push(c); totals.push({category:c, mainUnits:ca.mainUnits, subUnits:ca.subUnits});
    }
    else{
      o = totals[x]; o.mainUnits += ca.mainUnits; o.subUnits += ca.subUnits;
    }
  }
  return totals;
}
var cats = [
    {
        category: 'Category A',
        mainUnits: 5,
        subUnits: 3
    },

    {
        category: 'Category A',
        mainUnits: 9,
        subUnits: 12
    },

    {
        category: 'Category B',
        mainUnits: 4,
        subUnits: 6
    },

    {
        category: 'Category B',
        mainUnits: 2,
        subUnits: 4
    }
]
console.log(catTotals(cats));

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.