In my input array of object, I have a field called Grade. This is the filtering parameter

var input = [
 {
  "Qty": "2.00",
  "Grade": "AU27",
  "Thickness": "5.00",
  "Width": "1200.00",
 },
 {
  "Qty": "7.00",
  "Grade": "AU27",
  "Thickness": "10.00",
  "Width": "1400.00",
 },
 {
  "Qty": "17.00",
  "Grade": "AU27",
  "Thickness": "5.00",
  "Width": "1700.00",
 },
 {
  "Qty": "51.00",
  "Grade": "FE500D",
  "Thickness": "10.00",
  "Width": "1100.00",
 },
 {
  "Qty": "69.00",
  "Grade": "FE500D",
  "Thickness": "12.00",
  "Width": "1500.00",
 },
 {
  "Qty": "30.00",
  "Grade": "FE500D",
  "Thickness": "8.00",
  "Width": "1800.00",
 },
 {
  "Qty": "92.00",
  "Grade": "FE500D",
  "Thickness": "10.00",
  "Width": "2200.00",
 },
 {
  "Qty": "98.00",
  "Grade": "FE600D",
  "Thickness": "11.00",
  "Width": "2400.00",
 },
 {
  "Qty": "115.00",
  "Grade": "FE600D",
  "Thickness": "17.00",
  "Width": "2600.00",
 }
];

I want to create array of object called sumGradeArray from the above input array. If we consider the total quantities of different grades, irrespective of thickness and width, then total quantity of Grade AU27 is 2.00 + 7.00 + 17.00 = 26.00.

Similarly for grade FE500D total quantity is 51.00 + 69.00 + 30.00 + 92.00 = 242.00

Similarly for grade FE600D total quantity is 98.00 + 115.00 = 213.00

 var sumGradeArray = [
 {      
  "Grade": "AU27",
  "TotalQty": "26.00",
 },
 {      
  "Grade": "FE500D",
  "TotalQty": "242.00",
 },
 {      
  "Grade": "FE600D",
  "TotalQty": "213.00",
 },
];

Please someone provide me a generic solution using Vanilla JS(no Jquery/Lodash). I am showing just 3 grades here, in reality the input array of object is an API response. It can have hundreds of grades

3 Answers

2
Nina Scholz On Best Solutions

You could take a Map for grouping same grade and render the wanted style.

var input = [{ Qty: "2.00", Grade: "AU27", Thickness: "5.00", Width: "1200.00" }, { Qty: "7.00", Grade: "AU27", Thickness: "10.00", Width: "1400.00" }, { Qty: "17.00", Grade: "AU27", Thickness: "5.00", Width: "1700.00" }, { Qty: "51.00", Grade: "FE500D", Thickness: "10.00", Width: "1100.00" }, { Qty: "69.00", Grade: "FE500D", Thickness: "12.00", Width: "1500.00" }, { Qty: "30.00", Grade: "FE500D", Thickness: "8.00", Width: "1800.00" }, { Qty: "92.00", Grade: "FE500D", Thickness: "10.00", Width: "2200.00" }, { Qty: "98.00", Grade: "FE600D", Thickness: "11.00", Width: "2400.00" }, { Qty: "115.00", Grade: "FE600D", Thickness: "17.00", Width: "2600.00" }],
    result = Array.from(
        input.reduce((m, o) => m.set(o.Grade, (+(m.get(o.Grade) || 0) + +o.Qty).toFixed(2)), new Map),
        ([Grade, TotalQty]) => ({ Grade, TotalQty })
    );

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

1
Maheer Ali On

You can use reduce() and findIndex() for this.

var input = [ { "Qty": "2.00", "Grade": "AU27", "Thickness": "5.00", "Width": "1200.00", }, { "Qty": "7.00", "Grade": "AU27", "Thickness": "10.00", "Width": "1400.00", }, { "Qty": "17.00", "Grade": "AU27", "Thickness": "5.00", "Width": "1700.00", }, { "Qty": "51.00", "Grade": "FE500D", "Thickness": "10.00", "Width": "1100.00", }, { "Qty": "69.00", "Grade": "FE500D", "Thickness": "12.00", "Width": "1500.00", }, { "Qty": "30.00", "Grade": "FE500D", "Thickness": "8.00", "Width": "1800.00", }, { "Qty": "92.00", "Grade": "FE500D", "Thickness": "10.00", "Width": "2200.00", }, { "Qty": "98.00", "Grade": "FE600D", "Thickness": "11.00", "Width": "2400.00", }, { "Qty": "115.00", "Grade": "FE600D", "Thickness": "17.00", "Width": "2600.00", } ];

const res = input.reduce((ac,{Grade,Qty}) => {
  let index = ac.findIndex(x => x.Grade === Grade);
  index === -1 ? ac.push({Grade,totalQty:+Qty}) : ac[index].totalQty += +Qty
  return ac;
},[]).map(x => ({...x,totalQty:x.totalQty.toFixed(2)}))
console.log(res)

1
Jack On

Why do you want your quantities represented as strings in the end result when they are in fact numbers? And why not structure your object as { [grade]: <quantity> } as your object is now unique on grade and this will be easier to access and operate on?

My answer assumes you agree to do those two things

Code Snippet

var input = [
 {
  "Qty": "2.00",
  "Grade": "AU27",
  "Thickness": "5.00",
  "Width": "1200.00",
 },
 {
  "Qty": "7.00",
  "Grade": "AU27",
  "Thickness": "10.00",
  "Width": "1400.00",
 },
 {
  "Qty": "17.00",
  "Grade": "AU27",
  "Thickness": "5.00",
  "Width": "1700.00",
 },
 {
  "Qty": "51.00",
  "Grade": "FE500D",
  "Thickness": "10.00",
  "Width": "1100.00",
 },
 {
  "Qty": "69.00",
  "Grade": "FE500D",
  "Thickness": "12.00",
  "Width": "1500.00",
 },
 {
  "Qty": "30.00",
  "Grade": "FE500D",
  "Thickness": "8.00",
  "Width": "1800.00",
 },
 {
  "Qty": "92.00",
  "Grade": "FE500D",
  "Thickness": "10.00",
  "Width": "2200.00",
 },
 {
  "Qty": "98.00",
  "Grade": "FE600D",
  "Thickness": "11.00",
  "Width": "2400.00",
 },
 {
  "Qty": "115.00",
  "Grade": "FE600D",
  "Thickness": "17.00",
  "Width": "2600.00",
 }
];

const sumGradeArray = input.reduce((gradeSums, { Grade, Qty }) => 
    gradeSums[Grade] 
        ? { ...gradeSums, [Grade]: gradeSums[Grade] + Number(Qty) } 
        : { ...gradeSums, [Grade]: Number(Qty) }
    , {})
    
console.log(sumGradeArray);

// result:
{
    AU27: 26, 
    FE500D: 242, 
    FE600D: 213
}

Explanation

const sumGradeArray = input.reduce((gradeSums, { Grade, Qty }) => 

Here we perform a reduce. There is a better explanation at the link but essentially we are looping over the array, and saving whatever we return to the first parameter, in this case gradeSums. The second parameter is an item in the array, destructured here for quick access to the properties Grade and Qty.

gradeSums[Grade] 

If we have already saved a value for this grade, then we want to add the value in the current item to what we already have, result in this truthy statement:

? { ...gradeSums, [Grade]: gradeSums[Grade] + Number(Qty) } 

We spread the previous accumulated values so that we do not lose them.

: { ...gradeSums, [Grade]: Number(Qty) }

However, if we have not see it before we create a new entry for the quantity we have just seen.

, {})

Initial value should be an object so that we can spread it successfully.