Discovering all distinct intervals contained within a given interval

Looking to create a new array of arrays that contain the start and end numbers of intervals within a defined range without any overlaps. This scenario originated from managing timestamps of objects on a server.

For instance, if we have:

const intervals = [
  [3, 5],
  [7, 9],
];

const range = [2, 11];

The expected output would be [[2, 3], [5, 7], [9, 11]].

The intervals are sorted by start date without overlaps due to pre-processing according to this answer:

I have a working solution for this case but need help expanding it for other scenarios such as:

  1. Intervals: [[3, 5]]; Range: [4, 8]; Output: [[5, 8]]
  2. Intervals: [[7, 11]]; Range: [2, 8]; Output: [[2, 7]]
  3. Intervals: [[3, 5], [6, 8]]; Range: [4, 7]; Output: [[5, 6]]
  4. Intervals: [[5, 10], [15, 20], [25, 30]]; Range: [0, 35]; Output:
    [[0, 5], [10, 15], [20, 25], [30, 35]]

The current code checks for partial overlaps in cached dates before merging queries. Considering how to handle multiple cases efficiently with conditional statements or a universal function.

Answer №1

If you have a range of values, you can analyze the intervals and create a new array based on them.

const
    getInbetween = (intervals, range) => {
        const
            result = [];
            
        let value = range[0],
            index = 0;

        while (value < range[1] && index < intervals.length) {
            let [left, right] = intervals[index];
            if (value < left) result.push([value, left]);
            value = right;
            index++;
        }
        if (value < range[1]) result.push([value, range[1]]);
        return result;
    };

console.log(getInbetween([[3, 5], [7, 9]], [2, 11]));
console.log(getInbetween([[3, 5], [7, 9]], [4, 11]));
console.log(getInbetween([[3, 5], [7, 9]], [4, 8]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №2

Assuming the data is sorted and all intervals are merged, we only need to consider a few scenarios.

  1. The start of the range comes before the first element.
  2. The start of the range overlaps with the first element.
  3. The end of the range overlaps with the last element.
  4. The end of the range exceeds the last element.
  5. An element falls within the start and end of the range.
function getNonOverlappingIntervals(intervals, [rangeStart, rangeStop]) {
    const output = [];
    let prevStop = null;

    const intervalsInRange = intervals.filter(([start, stop]) => {
        if (rangeStart <= start && rangeStop >= stop) return true;
        if (start < rangeStart && stop > rangeStart) return true;
        if (start < rangeStop && stop > rangeStop) return true;
        return false;
    });

    // check if rangeStart precedes first interval
    if (intervalsInRange[0][0] > rangeStart) {
        output.push([rangeStart, intervalsInRange[0][0]]);
        prevStop = intervalsInRange[0][1];
    } else if (intervalsInRange[0][0] < rangeStart) {
        prevStop = intervalsInRange[0][1];
    }

    // iterate intervals and compare against last checked interval
    if (intervalsInRange.length > 2) {
        for (let i = 1; i < intervalsInRange.length; i++) {
            output.push([prevStop, intervalsInRange[i][0]]);
            prevStop = intervalsInRange[i][1];
        }
    }

    // check if rangeStop exceeds last interval
    if (intervalsInRange[intervalsInRange.length - 1][1] < rangeStop) {
        output.push([intervalsInRange.at(-1)[1], rangeStop]);
    }

    return output;
}

console.log(getNonOverlappingIntervals([[3, 5],[7, 9]], [2, 11]));
console.log(getNonOverlappingIntervals([[3, 5]], [4, 8]));
console.log(getNonOverlappingIntervals([[7, 11]], [2, 8]));
console.log(getNonOverlappingIntervals([[3, 5], [6, 8]], [4, 7]));
console.log(getNonOverlappingIntervals([[5, 10], [15, 20], [25, 30]], [0, 35]));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to update a knockout observable

Encountering a peculiar bug while attempting to update a user's address. The address object consists of two observable fields: stateProvince.name = ko.observable(""); stateProvince.code = ko.observable(""); When updating these values, the program ex ...

Adjust the time increment dynamically within the dropdown menu

I have a challenge to make a dynamic dropdown field that adjusts based on the value of a previous input field. There is a dropdown for selecting length, with options like 30 min., 60 min., and 90 min.. Additionally, there are input fields for startTime and ...

Is it possible to remove or delete a module in AngularJS?

Is there a way to clear the memory of a previous module in my app that I won't be using after routing to a different location? For instance, let's say my main Angular module is "WebApp" which has dependencies on modules like "catalogApp", "Payme ...

When initializing a local scope property as null in Angular.js, it may end up being undefined

Recently, I created a custom Angular directive. <location zipcode="35423" cityname="" statecode=""></location> Within the directive, I defined the following: scope: { zipcode: "@", cityname: "@", ...

Is it possible to execute a script from a different directory?

Currently, I am developing a nodejs package that involves executing a bash script within the program. The specific bash script, "./helpers/script.sh", needs to be run using a relative path. This means that when users install and run the package, the script ...

Whenever I attempt to invoke a generic handler through cross-domain using ajax, the data returned turns out to be undefined upon the successful

Whenever I use Ajax to call a generic handler across different domains, the data comes back as undefined in the success callback. function getUserInfo() { currentUser = null; $.ajax({ type: 'GET', ...

Utilizing async/await as a module function: A comprehensive guide

Express Route: const express=require('express'); const router=express.Router(); const trackRepo=require('../model/track'); router.post('/live',function(req,res){ const time=1439832167; const list=trackRepo.getAlerts ...

Utilizing PrimeVue for Seamless Theme-Change Functionality

Is there a way to change the theme using Prime Vue without directly modifying the index.html file with <link id="lara-light-indigo" rel="stylesheet" href="/themes/lara-light-indigo/theme.css">? Currently, I am managing ...

What is the best way to duplicate a DOM element or section?

I've been attempting to craft a stunning tree using D3. For the nodes, I have an SVG "template" tucked away in a hidden div. Despite my efforts with various D3 functions to replicate the "template," none were successful. The latest JavaScript snippe ...

What is the best way to share your NodeJS library, which is coded in TypeScript, to be compatible with both BrowserJS and NodeJS, while also taking advantage of

Similar to lodash, the library @yamato-daiwa/es-extensions offers common functions for both BrowserJS and NodeJS. However, unlike lodash, it has a single main file index.js with re-exports. Requirements This library: Must be compatible with browser envir ...

Enforcement of Typescript Field Type Lax During Assignment

My current issue involves a constructor that is supposed to set the value of _device. The field is specifically designed to be of type number, and the constructor parameter is also expected to be of type number. However, when a parameter of type string is ...

Angular is not programmed to automatically reflect updates made to my string array

let signalRServerEndPoint = 'https://localhost:44338'; this.connection = $.hubConnection(signalRServerEndPoint); this.proxy = this.connection.createHubProxy('MessagesHub'); this.proxy.on("ReceiveMessage", (message) => { ...

I am encountering an issue with the dropdown navigation menu in bootstrap

After creating a dropdown list using the code below, I encountered an issue where the sub-item "game" was not visible during implementation. Does this require any additional CDN? View the screenshot of the implementation. <head> <title>...& ...

Creating Unique Field Filters in Mongoose Using Variables

I am attempting to create a sophisticated search form that incorporates multiple criteria into a mongoose search. This is the approach I had in mind: router.post('/search/university', function(req, res) { var university = req.body.university.t ...

if two strings are BOTH found in a single array within a bash script

I need to verify if the strings "planning1" and "planning2" are both completely present in the array ("active","planning","delete"). Desired output: if both strings are present -> display "true" If one of the strings is missing from the list -> show ...

String Converted to Array of Key-Value Pairs

Looking to convert a key-value pair string into a functional array? Here's what I have so far: $Array = "'Type'=>'Honda', 'Color'=>'Red'"; $MyArray = array($Array); However, this code is not returning a ...

The div element with the id "wrapper" is not functioning properly within the box model

I have defined an ID wrapper in CSS: #wrapper { position: relative; background: yellow; -webkit-box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.2); box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.2); width: 960px; padding: 40px 35px 35px ...

Creating a comprehensive dataset before initiating an AJAX request using jQuery

I've developed a system that enables an admin to assign managers to a campaign through a table. Here's how the table is structured: <tr> <td>Checkbox</td> <td>Last name, First name</td> <td>Employee Id #</td ...

Is it possible to have data structures and TextView with virtually limitless capacity?

Seeking a widget similar to TextView but capable of displaying file contents of any size. The standard Android TextView can only handle and show 2^31 characters, equivalent to 2GiB. Similarly, other data structures like ArrayList, ByteArray, CharSequence, ...

Ways to enhance the dependability of Multiple Forms?

I am searching for efficient solutions for handling multiple forms. Take a look at the following example screenshot: In the dropdown, there are three networks - AT&T, Verizon Wireless, and T-Mobile. After selecting 'AT&T' from the drop ...