'use strict'; const stamps = require('./st.json'); // const stamps = [ // { value: 1, timestamp: new Date('2022-08-19T08:01:21.000Z') }, // { value: 1, timestamp: new Date('2022-08-19T08:01:22.000Z') }, // { value: 0, timestamp: new Date('2022-08-19T08:01:23.000Z') }, // { value: 0, timestamp: new Date('2022-08-19T08:01:24.000Z') }, // { value: 0, timestamp: new Date('2022-08-19T08:01:25.000Z') }, // { value: 1, timestamp: new Date('2022-08-19T08:01:29.000Z') }, // ]; // const timestamped = [ // { value: 1, timestamp: new Date('2022-08-19T08:01:21.000Z').getTime() }, // { value: 1, timestamp: new Date('2022-08-19T08:01:22.000Z').getTime() }, // { value: 0, timestamp: new Date('2022-08-19T08:01:23.000Z').getTime() }, // { value: 0, timestamp: new Date('2022-08-19T08:01:24.000Z').getTime() }, // { value: 0, timestamp: new Date('2022-08-19T08:01:25.000Z').getTime() }, // { value: 1, timestamp: new Date('2022-08-19T08:01:29.000Z').getTime() }, // ]; // const timestampedOther = [ // { value: 1, date: new Date('2022-08-19T08:01:21.000Z') }, // { value: 1, date: new Date('2022-08-19T08:01:22.000Z') }, // { value: 0, date: new Date('2022-08-19T08:01:23.000Z') }, // { value: 0, date: new Date('2022-08-19T08:01:24.000Z') }, // { value: 0, date: new Date('2022-08-19T08:01:25.000Z') }, // { value: 1, date: new Date('2022-08-19T08:01:29.000Z') }, // ]; // const t = new Timer(); class ProcessSensors { constructor(input) { this.input = input; this.startDate = null; this.endDate = null; } /** * Second slowest way. */ process() { const response = []; for (let i = 0; i < this.input.length; i++) { const object = this.input[i]; if (object.value === 0 && !this.startDate) this.startDate = object.timestamp; if (object.value === 1 && !this.endDate && this.startDate) this.endDate = object.timestamp; if (this.startDate && this.endDate) { response.push({ startDate: this.startDate, endDate: this.endDate, isShorterThanOneMin: this.endDate - this.startDate < 60_000, }); this.startDate = null; this.endDate = null; } } // console.log(response, 'processOne'); return response; } /** * Fastest way. */ processTwo() { const response = []; for (let i = 0; i < this.input.length; i++) { const pre = this.input[i]; const cur = this.input[i + 1] ?? {}; if (!cur.value && !cur.timestamp) continue; if (pre.value === 0 && !this.startDate) this.startDate = pre.timestamp; if (cur.value === 1 && !this.endDate && this.startDate) this.endDate = cur.timestamp; if (this.startDate && this.endDate) { response.push({ startDate: this.startDate, endDate: this.endDate, isShorterThanOneMin: this.endDate - this.startDate < 60_000, }); this.startDate = null; this.endDate = null; } } // console.log(response, 'processTwo'); return response; } /** * Approach of author of this question, found slowest. Maybe wrong. */ processAuthors() { const out = this.input.reduce((finalArray, currentValue, index, arr) => { if (currentValue.value === 0) { const resultElement = {}; resultElement.start = currentValue.timestamp; // find end Date let nextToCheck = index; let endFound = false; do { nextToCheck += 1; if (nextToCheck === arr.length) { break; } if (arr[nextToCheck].value === 1) { resultElement.end = arr[nextToCheck].timestamp; resultElement.isShorterThanOneMin = new Date(resultElement.end).getTime() - new Date(resultElement.start).getTime() < 60_000; endFound = true; } } while (!endFound); // find out if previous one was 1 --> if it was 0, it should not be pushed to avoid having sub-arrays if (index !== 0 && arr[index - 1].value !== 0) { finalArray.push(resultElement); } if (index === 0) { finalArray.push(resultElement); } } return finalArray; }, []); // console.log(out, 'author'); return out; } processOther() { const out = []; while (this.input.length > 0) { const input = this.input.shift(); if (this.previousInput === undefined) { this.previousInput = input.value === 0 ? input : undefined; continue; } if (this.previousInput.value === 0) { if (input.value === 0) continue; out.push({ startDate: this.previousInput.timestamp, endDate: input.timestamp, isShorterThanOneMinute: input.timestamp - this.previousInput.timestamp < 60000, }); this.previousInput = undefined; } } // console.log(out); return out; } } // new ProcessSensors(timestamped).process(); // new ProcessSensors(timestamped).processTwo(); // new ProcessSensors(stamps).processAuthors(); // new ProcessSensors(stamps).processOther(); const Benchmark = require('benchmark'); const suite = new Benchmark.Suite(); // add tests console.log(`Input length: ${stamps.length}`); suite .add('processOne', () => { new ProcessSensors(stamps).process(); }) .add('processTwo', () => { new ProcessSensors(stamps).processTwo(); }) .add('Author', () => { new ProcessSensors(stamps).processAuthors(); }) .add('Other', () => { new ProcessSensors(stamps).processOther(); }) .on('cycle', event => { console.log(String(event.target)); }) .on('complete', function () { console.log(`Fastest is ${this.filter('fastest').map('name')}`); }) .run({ async: true });