I have an object in the form of:
{
"Dates": ["January", "January", "March", "March", "March", "November", "November"],
"Values": [45.6, 0.5, 59.3, 46.56, 2.21, 48.59, 5.5]
}
What I need is to aggregate the values in "Values" (average) by month
The object I am seeking:
{
"Dates":["January", "March", "November"],
"Values":[23.05, 36.02, 27]
}
I know there have been several posts about it here. But I am not sure how to apply it to an object with arrays. Would appreciate very much any ideas. Thanks
CodePudding user response:
Something like this should work.
// First reduce the data to an object with the dates as keys
const grouped = data.Dates.reduce((acc, date, i) => {
if (acc[date]) {
acc[date].push(data.Values[i])
} else {
acc[date] = [data.Values[i]]
}
return acc
}, {});
// Then reduce the object to the desired format
const result = Object.keys(grouped).reduce((acc, date) => {
acc.Dates.push(date)
acc.Values.push(grouped[date].reduce((a, b) => a b) / grouped[date].length)
return acc
}, {Dates: [], Values: []});
CodePudding user response:
You could try something like this.
const obj = {
"Dates": ["January", "January", "March", "March", "March", "November", "November"],
"Values": [45.6, 0.5, 59.3, 46.56, 2.21, 48.59, 5.5]
}
// new Set() will remove all duplicated items
const months = [...new Set(obj.Dates)];
const result = {
"Dates": months,
"Values": months.map(month => {
// find values for given month
const values = obj.Values.filter((_, i) => obj.Dates[i] === month);
// sum the values and divide by the amount
return values.reduce((a, b) => a b) / values.length;
})
}
console.log(result);
CodePudding user response:
You could split the tasks into smaller parts and use functions for
- grouping,
- getting an average of an array
- getting the complete result by taking an object of groups.
const
getAverage = array => array.reduce((a, b) => a b) / array.length,
groupBy = (keys, values) => {
const groups = {};
for (let i = 0; i < keys.length; i )
(groups[keys[i]] ??= []).push(values[i]);
return groups;
},
getAverages = groups => Object.entries(groups).reduce((r, [month, values]) => {
r.Dates.push(month);
r.Values.push(getAverage(values));
return r;
}, { Dates: [], Values: [] }),
data = { Dates: ["January", "January", "March", "March", "March", "November", "November"], Values: [45.6, 0.5, 59.3, 46.56, 2.21, 48.59, 5.5] },
result = getAverages(groupBy(data.Dates, data.Values));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }