Reputation: 1164
I have a series of time slots:
[
"00:00-00:15",
"00:15-00:30",
.
.
.
"11:15-11:30",
"11:30-11:45",
"11:45-00:00"
]
I have a list of incoming time stamps along with some data which look like:
20:18 apple
20:07 bananas
00:12 apple
.
.
.
13:52 cake
I basically want to group these at the end and display something like:
.
.
20:15-20:30 apple 1 bananas 2,
20:30-20:45 cake 5,
20:45-21:00 apple 3, egg 1,
.
.
.
The approach I have thought of is iterating through all the time slots and finding which time slot can accommodate the time stamp. Is there anything better I can do to optimise it?
Also, I am unable to figure out how to store the frequency of multiple objects under a single time slot. Should I use JSON?
Here's my try. It has a lot of things going on. I have greatly simplified my problem statement to avoid any confusion but since Nina Scholz asked:
var express = require("express");
var router = express.Router();
var axios = require("axios");
function convertUTC(t) {
let unix_timestamp = t;
var date = new Date(unix_timestamp * 1000);
var hours = ("0" + date.getHours()).slice(-2);
var minutes = "0" + date.getMinutes();
var formattedTime = hours + ":" + minutes.substr(-2);
return formattedTime;
}
function generateTimeSlots() {
try {
var x = 15;
var times = [];
var tt = 0;
for (var i = 0; tt < 24 * 60; i++) {
hh = Math.floor(tt / 60);
mm = tt % 60;
beg = ("0" + (hh % 12)).slice(-2) + ":" + ("0" + mm).slice(-2);
hh = Math.floor((tt + 15) / 60);
mm = (tt + 15) % 60;
end = ("0" + (hh % 12)).slice(-2) + ":" + ("0" + mm).slice(-2);
times[i] = beg + "-" + end;
tt = tt + x;
}
return times;
} catch (error) {
console.log(error);
}
}
router.post("/process-logs", async (req, res) => {
fileStrings = req.body.logFiles;
parallelCount = req.body.parallelFileProcessingCount;
times = generateTimeSlots();
for (var i = 0; i < fileStrings.length; i++) {
await axios.get(fileStrings[i]).then(function (response) {
lines = response.data.split(/\r?\n/);
for (var j = 0; j < lines.length; j++) {
time = convertUTC(lines[j].split(" ")[1]);
console.log(time);
}
});
}
res.send(times);
res.send("done");
});
module.exports = router;
Upvotes: 0
Views: 532
Reputation: 24565
A very simple and naive approach (with O(n^2) time complexity) that works for arbitrary ranges would be to create a helper map, iterate through each of the slots and find the matching timestamps. If there's a match update the count for the corresponding fruit in the map. Something like this:
const slots = [ '00:00-00:15', '11:30-11:45', '13:25-14:00', '20:00-20:30'];
const data = ['20:18 apple','00:11 apple', '20:07 bananas', '20:27 bananas', '00:12 apple', '13:52 cake', '11:22 cake'];
function groupTimeslots(slots, fruitData) {
const timeSlotMap = {};
for (const key of slots) {
timeSlotMap[key] = {};
}
for (const slot of slots) {
for (const entry of fruitData) {
const [timestamp, fruit] = entry.split(' ');
if (isBetween(slot, timestamp)) {
timeSlotMap[slot][fruit] = timeSlotMap[slot][fruit] ? ++timeSlotMap[slot][fruit] : 1;
}
}
}
return timeSlotMap;
}
function isBetween(slot, timestamp) {
const [start, end] = slot.split('-');
const timestampMins = toMinutes(timestamp);
return timestampMins > toMinutes(start) && timestampMins < toMinutes(end);
}
function toMinutes(timestamp) {
const [hours, minutes] = timestamp.split(':');
return Number.parseInt(hours) * 60 + Number.parseInt(minutes);
}
console.log(groupTimeslots(slots, data));
Upvotes: 1
Reputation: 5245
You can assign the index to a particular time slot. Then we can convert an incoming time to the index.
An index could be calculated by how many "slots" proceeds the particular time, sou we could divide the time in minutes by 15 to get the index.
[
"00:00-00:15", // 0th -> index = 0
"00:15-00:30", // 1st -> index = 1
.
.
.
"11:15-11:30", // 93th
"11:30-11:45", // 94th
"11:45-00:00" // 95th -> index = 95
]
const indexToTime = (index) => {
const hour = Math.floor(15 * index / 60) % 24
const minute = (15 * index) % 60
const h = `${hour}`.padStart(2, 0)
const m = `${minute}`.padStart(2, 0)
const time = `${h}:${m}`
return time
}
const timeToIndex = (time) => {
const [hour, minute] = time.split(':')
const [h, m] = [parseInt(hour), parseInt(minute)]
const index = hour * 4 + Math.floor(minute / 15)
return index
}
const slots = [...Array(24 * 60 / 15)].map((_, i) => `${indexToTime(i)}-${indexToTime(i+1)}`)
console.log('slots =', slots)
const records = ['20:47 apple', '20:18 apple', '20:17 bananas', '20:43 cake', '20:18 bananas', '20:31 cake', '20:30 cake', '20:40 cake', '20:39 cake', '20:49 apple', '20:54 egg', '20:50 apple']
console.log('records =', records)
const stats = []
records.forEach(record => {
const [time, item] = record.split(' ')
const index = timeToIndex(time)
if (!stats[index]) {
stats[index] = {[item]: 1}
} else if(!stats[index][item]) {
stats[index][item] = 1
} else {
stats[index][item]++
}
})
console.log('stats =', stats)
const statsRecords = slots.map((time, index) => ({ time, stats: stats[index] }))
console.log('statsRecords =', statsRecords)
const display = (statsRecords) => {
return statsRecords.map(({ time, stats = {} }) => `${time} ${Object.entries(stats).map(([item, count]) => `${item} ${count}`).join(', ')}`).join('\n')
}
console.log(display(statsRecords))
Upvotes: 0