I am relatively new to programming and javascript and i want to achieve the following. Let's assume that we have the following data:
let data =
[
{
"time": 1663163352001,
"state": "10"
},
{
"time": 1663163352002,
"state": "20"
},
{
"time": 1663163354002,
"state": "10"
},
{
"time": 1663163354002,
"state": "10"
},
{
"time": 1663163355033,
"state": "30"
},
{
"time": 1663163355035,
"state": "10"
},
{
"time": 1663163397035,
"state": "30"
},
{
"time": 1663163397044,
"state": "50"
}
]
i want to aggregate and calculate the averaged state based on timestamps on time interval (let's say 1 second) so the output should be
let data =
[
{
"time": 1663163352000,
"state": "15"
},
{
"time": 1663163353000,
"state": "0"
},
{
"time": 1663163354000,
"state": "10"
},
{
"time": 1663163355000,
"state": "20"
},
{
"time": 1663163356000,
"state": "0"
},
{
"time": 1663163397000,
"state": "40"
}
]
I know my code is not right but at this is the logic that i have already implement.
//Inputs
var t_interval = 1000;
let aggregatedValues = [];
let count = 0;
let sum = 0;
//starting point converted in seconds
t0 = data[0].time - data[0].time % 1000;
//the timewindow
t_win = t0 t_interval;
//Just for this case
for (let i = 0; i < 7; i ) {
if ( data[i].time < t_win) {
count = 1;
sum = parseFloat(data[i].state);
}
else{
if (sum === 0 || count === 0) {
avg = NaN;
}
avg = sum / count;
count = 1;
sum = parseFloat(data[i].state);
let temp = {
"time": t_win - t_interval,
"state": avg
}
aggregatedValues.push(temp);
t_win = t_win t_interval;
}
}
Could you help me please? Thank you!
CodePudding user response:
Pretty simple task, reduce
over your collection to create an object with key
= timestamp
and value
= object
of total amount of states
and count
of met items. Apply some rounding operation on timestamp. Then 1 more loop to calculate average values. Convert it back to array and sort (if needed). Gaps filling is up to you.
const data = [
{ time: 1663163352001, state: "10" },
{ time: 1663163352002, state: "20" },
{ time: 1663163354002, state: "10" },
{ time: 1663163354002, state: "10" },
{ time: 1663163355033, state: "30" },
{ time: 1663163355035, state: "10" },
{ time: 1663163397035, state: "30" },
{ time: 1663163397044, state: "50" }
];
function aggregate(items) {
const step = 1000 * 1; // 1 second
const resObj = items.reduce((acc, item) => {
const roundedTimestamp = Math.round(item.time / step) * step;
const parsedValue = parseInt(item.state, 10);
const existing = acc[roundedTimestamp];
if (!existing) {
acc[roundedTimestamp] = {
count: 1,
value: parsedValue
};
} else {
existing.count = 1;
existing.value = parsedValue;
}
return acc;
}, {});
const res = Object.entries(resObj)
.map(([key, value]) => ({
time: parseInt(key, 10),
value: (value.value / value.count).toString()
}))
.sort((a, b) => a.time - b.time);
// fill gaps if you really need that.
//
return res;
}
console.log(aggregate(data));