Reputation: 2886
I have an array of objects with this structure:
[
costBreakdown: {
flexMeetAncCost: "1,274,051",
flexOneTimeCosts: "0",
flexSeatCharges: "2,403,869",
tradFacilMgmtCost: "134,437",
tradOneTimeTotalCost: "1,462,049",
tradRentCost: "1,572,738",
},
costBreakdown: {
flexMeetAncCost: "1,279,524",
flexOneTimeCosts: "0",
flexSeatCharges: "2,414,197",
tradFacilMgmtCost: "135,025",
tradOneTimeTotalCost: "1,467,029",
tradRentCost: "1,579,576",
},
]
and I'm trying to iterate through all of these objects and find the average for every key after parsing the strings and to make it a whole number, then output one object of the aggregate.
const { mean } = require('lodash')
const result = allLambdas.reduce((acc, currValue, index, array) => {
const aggregateCostBreakdown = (key) => (
Math.round(mean(array.map((obj) => parseFloat(obj.costBreakdown[key].replace(/,/g, ''))))).toLocaleString('en')
)
const avgCostBreakdown = {
flexMeetAncCost: aggregateCostBreakdown('flexMeetAncCost'),
flexOneTimeCosts: aggregateCostBreakdown('flexOneTimeCosts'),
flexSeatCharges: aggregateCostBreakdown('flexSeatCharges'),
tradFacilMgmtCost: aggregateCostBreakdown('tradFacilMgmtCost'),
tradOneTimeTotalCost: aggregateCostBreakdown('tradOneTimeTotalCost'),
tradRentCost: aggregateCostBreakdown('tradRentCost')
}
acc.costBreakdown = avgCostBreakdown
return acc
}, {
costBreakdown: {},
}
)
While this seemingly works, I don't think I should ever be referencing the array
argument in the reduce
function as this seems not performant.
How do I get the average of these array of objects and output them out into just one object?
Upvotes: 1
Views: 62
Reputation: 1917
You can try something like this, where you first sum the values and keep the count and then you find the mean of each prop. Hope this helps.
const data = [{
costBreakdown: {
flexMeetAncCost: "1,274,051",
flexOneTimeCosts: "0",
flexSeatCharges: "2,403,869",
tradFacilMgmtCost: "134,437",
tradOneTimeTotalCost: "1,462,049",
tradRentCost: "1,572,738",
} },{
costBreakdown: {
flexMeetAncCost: "1,279,524",
flexOneTimeCosts: "0",
flexSeatCharges: "2,414,197",
tradFacilMgmtCost: "135,025",
tradOneTimeTotalCost: "1,467,029",
tradRentCost: "1,579,576",
},
}
];
const findMeans = (arr) => {
const summed = arr.reduce((acc, { costBreakdown }) => {
Object.keys(costBreakdown).forEach((key) => {
const n = parseFloat(costBreakdown[key].replace(',', '.'));
acc.costBreakdown[key] = acc.costBreakdown[key] ? { value: acc.costBreakdown[key].value + n, count: acc.costBreakdown[key].count + 1 } : { value: n, count: 1 }
});
return acc;
}, { costBreakdown: {} });
return Object.keys(summed.costBreakdown).reduce((acc, val) => {
acc.costBreakdown[val] = summed.costBreakdown[val].value / summed.costBreakdown[val].count;
return acc;
}, { costBreakdown: {} });
};
console.log(findMeans(data));
Upvotes: 1
Reputation: 116
If I understand correctly you need to reduce the array to an object of the same structure as the elements inside the array but the values for the properties in the resulting array should be the average of all co-responding props of the elements, right?
Might be something like this should work:
const convertToNumber = parseFloat; // make your own implementation
const allLambdasLength = allLambdas.length;
const result = allLambdas.reduce((acc, currValue, index) => {
if(index < allLambdasLength - 1) {
return {
flexMeetAncCost: acc.flexMeetAncCost + convertToNumber(currValue.flexMeetAncCost),
// do this for all keys in the object
...
};
} else {
return {
costBreakdown: {
flexMeetAncCost: acc.flexMeetAncCost / allLambdasLength,
// do this for all keys in the object
...
}
};
}
}, {})
Upvotes: 0