Search code examples
javascriptarraysobjectreduce

How to sum values of certain properties for each subgroup nested array object's in Javascript?


From the object below, I wanted to sum up certain properties (fare+tax and com+agency) by their key group (1345, 2353) and updated it in the current array object.

var details = [{ 1345:[
                {route: 34, fare: 45, tax: 46, date: 46, com: 45, agency: 24, totalCost: 0, totalFee: 0}], 
               2353: [
                {route: 32, fare: 45, tax: 45, date: 56, com: 34, agency: 52, totalCost: 0, totalFee: 0}, 
                {route: 42, fare: 34, tax: 64, date: 34, com: 56, agency: 34, totalCost: 0, totalFee: 0}
              ]} 
             ]

expected output: updated details (totalCost and totalFee)

    1345: 
{ route: 34, fare: 45, .... totalCost: 91, totalFee: 69 }
    2353: 
{ route: 32, fare: 45, ... totalCost: 188, totalFee: 90 },
{ route: 42, fare: 34, ... totalCost: 188, totalFee: 176 }

totalCost = fare + tax and totalFee = com + agency

I tried to simplified the array objects and convert by using Object.entries(details[0]), then reduce to sum up the target properties.

Object.entries(details[0]).reduce((acc, curr) => (acc = acc + curr["fare"]+curr["tax"]), 0);

However, NaN was returned.

Would appreciate if anyone could show me how I can loop through each key group and sum up the target values and update it (totalCost and totalFee).


Solution

  • One way (of many) would be to use a simple sum function to sum up an arbitrary array of values:

    function sum(...nums) {
      return nums.reduce((acc, val) => acc + val)
    }
    

    Next, sum up the totalCost/totalFee logic for each key group (1345 and 2353), and then apply the sums to each array entry:

    for (const [key, vals] of Object.entries(details[0])) {
      vals.forEach((val, _, vals) => {
        val.totalFee  = sum(...vals.map(val => val.com + val.agency))
        val.totalCost = sum(...vals.map(val => val.fare + val.tax))
      })
    }
    

    Here's the whole shebang:

    const details = [
      {
        1345: [
          {route: 34, fare: 45, tax: 46, date: 46, com: 45, agency: 24, totalCost: 0, totalFee: 0},
        ], 
        2353: [
          {route: 32, fare: 45, tax: 45, date: 56, com: 34, agency: 52, totalCost: 0, totalFee: 0}, 
          {route: 42, fare: 34, tax: 64, date: 34, com: 56, agency: 34, totalCost: 0, totalFee: 0},
        ],
      },
    ]
    
    for (const [key, vals] of Object.entries(details[0])) {
      vals.forEach((val, _, vals) => {
        val.totalFee  = sum(...vals.map(val => val.com + val.agency))
        val.totalCost = sum(...vals.map(val => val.fare + val.tax))
      })
    }
    
    console.log(JSON.stringify(details, null, 2))
    
    function sum(...nums) {
      return nums.reduce((acc, val) => acc + val)
    }