Reputation: 758
I have some data by the hour and summarise/consolidate the array.
However, there are some hours which are blank in data.Items
hence my array would skip the data point completely.
Is there a way where I can through my data/array and fill in the gaps and assign a '0' next to it?
for(i=0; i<dataLength; i++){
var date = new Date(data[i].ctimestamp);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
var date = moment(date).tz("Pacific/Auckland").format("DD/MM/YY HH:mm");
dateArray.push({"date" : date});
}
Here is an example - "11/12/18 05:00" and "11/12/18 06:00" are missing so it's skipped completely.
[{
"date": "11/12/18 08:00",
"count": 5
},
{
"date": "11/12/18 07:00",
"count": 4
},
{
"date": "11/12/18 04:00",
"count": 6
}]
Ideally, I would like it to show:
[
{
"date": "11/12/18 08:00",
"count": 5
},
{
"date": "11/12/18 07:00",
"count": 4
},
{
"date": "11/12/18 06:00",
"count": 0
},
{
"date": "11/12/18 05:00",
"count": 0
},
{
"date": "11/12/18 04:00",
"count": 6
}]
Upvotes: 0
Views: 202
Reputation: 14927
I think this simplifies the logic and produces the result you want:
const data = [
{
"date": "11/12/18 08:00",
"count": 5
},
{
"date": "11/12/18 07:00",
"count": 4
},
{
"date": "11/12/18 04:00",
"count": 6
}
];
let min = Number.MAX_VALUE;
let max = 0;
const dates = data.reduce((memo, {date, count}) => {
const time = new Date(date).getTime();
min = Math.min(min, time);
max = Math.max(max, time);
memo[time] = count;
return memo;
}, {});
const ONE_HOUR = 60 * 60 * 1000;
const dataOutput = [];
for (let i = min;i <= max;i += ONE_HOUR) {
dataOutput.push({
date: new Date(i).toLocaleString(),
count: dates[i] || 0
});
}
console.log(dataOutput)
Upvotes: 1
Reputation: 2494
I'll assume the array you posted as sample data, is called dataItems. Also, I'll use moment to handle time, but you can convert it to vanilla JS if you want.
So, what I would do is go through dataItems, and check if prev value is 1 hour prev to this value, if its not, add a new input.
dataItems.reduce((acc, val) => {
if(!acc) {
return [moment(val)];
}
let momentVal = moment(val)
if (momentVal.diff(acc[acc.length - 1], 'hours') !== 1){
acc.push(momentVal)
return acc;
} else {
while(momentVal.diff(acc[acc.length - 1], 'hours') !== 1){
acc.push(moment(acc[acc.length - 1]).add(1, 'hours')) //clone and add 1 hour
}
}
}])
I didn't take in consideration your object isn't just date, but that should be simple to adapt. The general logic is: go through your array, if the previous one is 1 hour less than right now, keep it going. Else, add a new input until the actual one is 1 hour after the last one on the array
Upvotes: 1