Minimize an array by organizing objects based on the proximity of their numbers

My array contains the following data:

[  
  { "begin": 870, "end": 889, "spanType": ["plan", "gt-plan"] },
  { "begin": 890, "end": 925, "spanType": ["plan", "gt-plan"] },
  { "begin": 926, "end": 938, "spanType": ["plan", "gt-plan"] },
  { "begin": 939, "end": 958, "spanType": ["plan", "gt-plan"] },
  { "begin": 7732, "end": 7790, "spanType": ["plan", "gt-plan"] },
  { "begin": 7791, "end": 7879, "spanType": ["plan", "gt-plan"] }
]

I am trying to iterate over this array and create a new array with the following structure:

[  
  { "begin": 870, "end": 958, "spanType": ["plan", "gt-plan"] },
  { "begin": 7732, "end": 7879, "spanType": ["plan", "gt-plan"] }
]

The goal is to merge two spans together if the end of one span is within 3 units of the beginning of the next span.

This is my current approach (not functioning as intended) - check it out on this demo link:

spans.forEach(function(d,i) {
    if (i+1 <= spans.length - 1) {
    if (spans[i+1].begin <= d.end + 3) {
    d.end = spans[i+1].end;
     newSpans.push(d);
  }
    else {
        newSpans.push(spans[i]);
    }
  }
});

Link to the demo for reference - see fiddle

Answer №1

First step would be to organize the spans in a sorted manner to avoid continuously checking all elements:

spans.sort((a,b) => a.begin - b.begin);

With the spans sorted, we can efficiently merge them together:

const result = [];
result.push(spans.reduce((prev,curr) => {
 if(prev.end < curr.begin - 1){
  result.push(prev);
  return Object.assign({},curr);
 }
 prev.end = Math.max(prev.end, curr.end);
 return prev;
}));

Give it a try

Answer №2

When dealing with sorted data, it becomes easier to compare the last inserted element with the current one and make adjustments to the 'end' value if the difference is smaller than a specified number.

This approach modifies the original array. If you prefer to avoid altering the original array, consider creating a copy of the object when pushing.

var list = [{ begin: 870, end: 889, spanType: ["plan", "gt-plan"] }, { begin: 890, end: 925, spanType: ["plan", "gt-plan"] }, { begin: 926, end: 938, spanType: ["plan", "gt-plan"] }, { begin: 939, end: 958, spanType: ["plan", "gt-plan"] }, { begin: 7732, end: 7790, spanType: ["plan", "gt-plan"] }, { begin: 7791, end: 7879, spanType: ["plan", "gt-plan"] }],
    output = list.reduce(function (result, obj, index) {
        if (!index || obj.begin - result[result.length - 1].end >= 3) {
            result.push(obj);
        } else {
            result[result.length - 1].end = obj.end;
        }
        return result;
    }, []);

console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №3

const dataList = [  
  { "start": 870, "finish": 889, "type": ["plan", "gt-plan"] },
  { "start": 890, "finish": 925, "type": ["plan", "gt-plan"] },
  { "start": 926, "finish": 938, "type": ["plan", "gt-plan"] },
  { "start": 939, "finish": 958, "type": ["plan", "gt-plan"] },
  { "start": 7732, "finish": 7790, "type": ["plan", "gt-plan"] },
  { "start": 7791, "finish": 7879, "type": ["plan", "gt-plan"] }
];

// set the range for merging end values
const MERGE_RANGE = 3;

// loop through the available data objects
for (let index = 0; index < dataList.length - 1; index++) {
    // check if merging is necessary based on range condition
    if (dataList[index].finish >= dataList[index+1].start - MERGE_RANGE) {
        // merge current object into the next one
        // adjust start value and combine type entries
        dataList[index+1].start = dataList[i].start;
        Array.prototype.push.apply(dataList[index+1].type, dataList[index]);
        dataList.splice(index, 1);  // remove merged object
        index--;  // adjust index after removal
    }
}
console.log(dataList);

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

What is the method for subtracting pixels from a percentage value?

Is there a way to accomplish a similar effect to this: height: calc(100% - 50px); height: -webkit-calc(100% - 50px); height: -moz-calc(100% - 50px); In browsers that do not support these properties? I have a responsive div with two children. The height ...

Concerns surrounding obtaining a response while using the $.get() method

$('#requestButton').click(function() { $.get('ajax.php', function(data) { alert(data); }); }); Why is the alert() not appearing after the click event? ...

Exploring ways to retrieve elements from a subarray in Java using indexes instead of keys

Looking at a JSON structure: { "Message": "None", "PDFS": [ [ "test.pdf", "localhost/", "777" ], [ "retest.pdf", "localhost\", "666" ] ], "Success": true } An attempt ...

Using React/NextJS: What is the best way to handle mapping through an array of objects with dynamic keys?

I am currently working on a project in NextJS and have encountered an interesting challenge that I'm struggling to solve. The issue revolves around dealing with an array of objects obtained from the Civic GAPI. Within this array, there are objects rep ...

Basic animation feature malfunctioning

So, I'm really new to this whole HTML5 canvas thing and I'm trying to make a pixel move across the screen with an additive tail behind it. The idea is for the tail to scroll away once it reaches a certain point while the pixel continues moving. I ...

Create and export a React component with dual properties

Currently, I am utilizing MaterialUI in my project and exporting components in the following manner: import withStyles, { WithStyles } from "@material-ui/core/styles/withStyles"; ... export default withStyles(styles)(Users); Recently, I have integrated ...

Support for Vue 3.4 same-name shorthand has been added to VS Code

After upgrading my Vue 3 project to version 3.4, I encountered an issue with vs-code highlighting same-name shorthand as an error, even though it was functioning correctly in my code. I am using the volar extension. Is there a way to resolve this so that v ...

Ensure that clicking on various links will result in them opening in a new pop-up window consistently

I am facing an issue with my HTML page where I have Four Links that are supposed to open in separate new windows, each displaying unique content. For instance: Link1 should open in Window 1, Link2 in Window 2, and so on... The problem I'm encounter ...

Is there a way to determine if the browser window is currently in use?

The code I am currently working with looks like this: let focus; function setFocus() { focus = true; } function hideWindow() { focus = false; } window.onfocus = setFocus(); window.onblur = hideWindow(); The intention behind this code is to use it in the ...

Problematic situation when using ng-repeat with dynamic ng-include and template variables scope conflict

When utilizing ng-repeat with dynamic ng-include that includes variables, the variables are not being properly recognized. Take a look at this code snippet. Here is the main HTML code: <table style> <tr> <th>Student</th> ...

Combining two animated gifs using JavaScript: A step-by-step guide

In my current project, I have developed a web application that allows users to upload animated gifs. Through this application, users can place the gifs on the webpage using <img> tags and move them around as they please. After the user finishes arran ...

Can you explain how JSON and AJAX are different when used in conjunction with jQuery?

Is it true that JSON serializes all data, preventing problems with client-side issues like cross-browser support? I've found using AJAX with jQuery to be straightforward, but I'm still unclear about the differences. I have also come across anot ...

Babel had a SyntaxError in test.jsx file at line 3, position 11 with an Unexpected token

Having trouble converting JSX to JS with Babel? If you're seeing an error like the one below, don't worry - we can help you fix it: The example code in test.jsx is causing a SyntaxError when transformed using babel test.jsx: SyntaxError: test ...

Javascript Parameter

Each time I enter scroll(0,10,200,10); into my code, it seems to output the strings "xxpos" or "yypos" instead of the actual values. I attempted to remove the apostrophes around them, but unfortunately, that did not resolve the issue. scroll = function( ...

Having trouble correctly parsing XML data using JavaScript

My input field contains the following XML code: <?xml version="1.0" encoding="utf-8"?> <players timestamp="1536505850"> <player id="0518" name="Eagles, Philadelphia" position="Def" team="PHI" /> <player id="10271" name="Jones, Jul ...

Tips for managing the output of an asynchronous function in TypeScript

The casesService function deals with handling an HTTP request and response to return a single object. However, due to its asynchronous nature, it currently returns an empty object (this.caseBook). My goal is for it to only return the object once it has b ...

Having trouble fetching AJAX POST data in PHP?

Attempting to send a variable as an object to my PHP file, but it's not receiving any data. Testing with window.alert(u.un) in the AJAX call shows that data is being passed successfully without errors in the console. However, the PHP file still does n ...

The process of incorporating types into Node.js and TypeScript for handling req and res objects

Check out the repository for my project at https://github.com/Shahidkhan0786/kharidLoapp Within the project, the @types folder contains a file named (express.d.ts) where I have added some types in response. The (express.d.ts) file within the @types folde ...

Browser freezes unexpectedly every 10-15 minutes

I have an application that displays 10 charts using dygraphs to monitor data. The charts are updated by sending ajax requests to 4 different servlets every 5 seconds. However, after approximately 10-15 minutes, my browser crashes with the "aw! snap" messag ...

Callback function for asynchronous operations on the client side with Meteor

Is there a way to retrieve the value returned by an asynchronous callback in the client-side of Meteor before the stack continues executing? Here is code snippet as an example: var result=function(str){ Meteor.call("getSearch",str,function(err,res){ ...