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

Time:08-31

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

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:

1345: { ..., totalCost: 91, totalFee: 69 }
2353: {..., totalCost: 188, totalFee: 90 }

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).

CodePudding user response:

One way (of many) would be to initialize a totals object in the format you want.

const totals = {}

for (const key in details[0]) {
  totals[key] = {
    totalCost: 0,
    totalFee: 0,
  }
}

Then use a simple sum function to sum up an arbitrary array of values:

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

The rest is pretty simple: Sum based on your totalCost/totalFee logic:

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

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},
    ],
  },
]

const totals = {}

for (const key in details[0]) {
  totals[key] = {
    totalCost: 0,
    totalFee: 0,
  }
}

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

console.log(totals)

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

CodePudding user response:

We can do this using a few Array.reduce() calls, the end result should be as required.

For each key group, we'd use Object.entries() to get the key and value for the group.

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} ]} ]
         
const result = details.reduce((acc, group) => { 
    return Object.entries(group).reduce((acc, [key, routes] ) => {
        return routes.reduce((acc, { fare, tax, com, agency}) => { 
            acc[key] = acc[key] || {};
            acc[key].totalCost = (acc[key].totalCost || 0)   fare   tax;
            acc[key].totalFee = (acc[key].totalFee || 0)   com   agency;
            return acc;
        }, acc)
    }, acc)
}, {})

console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

CodePudding user response:

Expanding on the use of Object.values

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}
              ]} 
             ]

Object.values(details).map(x => {
  details = []
  let count = 0;
  for (let y of Object.values(x)) {
    y = y.reduce(function (a, b) {
      for (const key in b) {
        if (a[key]) {
          a[key] = a[key]   b[key]
        } else {
          a[key] = b[key];
        }
      }
      return a;
    }, {});
    y['totalCost'] = y['fare']   y['tax']; 
    y['totalFee'] = y['com']   y['agency'];
    let totalObj = {};
    totalObj[`${Object.keys(x)[count]}`] = `totalCost: ${y['totalCost']}, totalFee: ${y['totalFee']}` 
    details.push(totalObj)
    count  ;
  };
});

console.log(details);

  • Related