I have an array of object that looks like that:
[{
TIMESTAMP: "2021-05-07 03:32:00.0",
PM2_5: "27.4",
PM10: "67.9",
CO: "0.058",
},
{
TIMESTAMP: "2021-05-07 03:42:00.0",
PM2_5: "27.0",
PM10: "67.3",
CO: "0.026",
},
{
TIMESTAMP: "2021-05-07 04:08:00.0",
PM2_5: "27.0",
PM10: "67.3",
CO: "0.066",
}
...]
There's more data ofc. I want to do a function that will take my array as a parameter and return an array of object. In this return array I want to merge all the object with the same hour timestamp together and do an average off all of their properties. I don't know which property they will have and the number can vary. So that I can have one object for each hour. For example for all the object at 3h, I will have
{
TIMESTAMP: "2021-05-07 03:00:00.0",
PM2_5: "27.2",
PM10: "67.3",
CO: "0.046",
}
For the 3h range I will have the average of all the data resume in one object.And I want to do this for all the hours I can have in the array. I tried to use reduce, or do a big loop, but my problem is that I don't want to precise the key in my loop I want it to work for all the keys that can exist.
function getAverage(datas) {
const res = []
datas.forEach((data, i) => {
if (moment.tz(data.TIMESTAMP, 'YYYY-MM-DD HH:mm:ss', TIMEZONE).hour() === moment.tz(datas[i 1].TIMESTAMP,'YYYY-MM-DD HH:mm:ss', TIMEZONE).hour()) {
data = data.PM10
}
res.push(data / i)
i = 0
})
return res
}
I did that for now but it's really far from the result I want
CodePudding user response:
I have generated a custom logic to generate the output as per the requirement.
You can find the details of logic and implementation in the code comment.
Working Fiddle
const data = [{
TIMESTAMP: "2021-05-07 03:32:00.0",
PM2_5: "27.4",
PM10: "67.9",
CO: "0.058",
},
{
TIMESTAMP: "2021-05-07 03:42:00.0",
PM2_5: "27.0",
PM10: "67.3",
CO: "0.026",
},
{
TIMESTAMP: "2021-05-07 04:08:00.0",
PM2_5: "27.0",
PM10: "67.3",
CO: "0.066",
}];
function getAverage(datas) {
const output = datas.reduce((acc, curr) => {
// Convert the date string.
// Replace all minutes and seconds with :00
// Replace milliseconds with .0
const timestr = curr.TIMESTAMP
.replaceAll(/:\d{2}/gm, ":00")
.replaceAll(/\.\d/gm, ".0");
// If the node with this parsed date string is avilable in accumulator, modify that node
if (acc[timestr]) {
// Increment the total against that particular timestamp
acc[timestr].total;
// Generate unique keys from the node in accumulator and from the current node in the data array
const keys = [...new Set([...Object.keys(acc[timestr]), ...Object.keys(curr)])];
// Loop through the keys and add that to node in accumulator.
keys.forEach((key) => {
// Donot modify key 'TIMESTAMP'
if (key !== 'TIMESTAMP') {
acc[timestr][key] = ( acc[timestr][key] || 0) ( curr[key] || 0);
}
})
} else {
// If the node with this parsed date string is not available in accumulator, add that node
acc[timestr] = { ...curr, TIMESTAMP: timestr, total: 1 };
}
return acc;
}, {});
// Generate average
// The result of accumulator is an object
// Convert it into Array using `Object.values(output)` and run `Array.map`
const result = Object.values(output).map((node) => {
// create an object rest from the value with out key total and TIMESTAMP
const { total, TIMESTAMP, ...rest } = node;
// Find avarage of each key
Object.entries(rest).forEach(([key, value]) => rest[key] = rest[key] / total);
// Return parsed node
return { ...rest, TIMESTAMP };
})
return result;
}
console.log(getAverage(data));