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