Home > Net >  Returning an object with the average of the properties which have the same hour timestamp
Returning an object with the average of the properties which have the same hour timestamp

Time:02-18

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

  • Related