What is the best way to insert zeros within a sequence of numbers in an array?

An example of an arbitrary number sequence is provided below:

const numbers = [
  
    0, 0, 0, 0, 0,
    12, 64, 9, 6,
    0, 0, 0, 
    25, 79, 57, 13, 39,
    0, 0,
    7, 7,
    0, 0, 0, 0, 0,
    49,
    0
  
]; 

The task at hand is to replace all zero values with interpolated values derived from their non-zero neighbors. The expected output for the updated sequence is as follows:

const updatedNumbers = [
  
    12, 12, 12, 12, 12,
    12, 64, 9, 6,
    10.75, 15.5, 20.25,
    25, 79, 57, 13, 39,
    28.3333, 17.6666,
    7, 7,
    14, 21, 28, 35, 42,
    49,
    49
  
];

In cases where a zero value is located at the beginning or end of the sequence without both left and right non-zero neighbors, the zero value is replaced accordingly.

The code snippet provided demonstrates a solution to this problem by identifying sequences of zeros in the initial array, finding their neighboring non-zero elements, and then calculating and replacing the interpolated values within those sequences.

Answer №1

Just a little bit more and you'll have it, rely on the interpolateValues function to handle those tricky edge cases with ease.

let sequence = [
  0, 0, 0, 0, 0,
  12, 64, 9, 6,
  0, 0, 0,
  25, 79, 57, 13, 39,
  0, 0,
  7, 7,
  0, 0, 0, 0, 0,
  49,
  0
];

const interpolateValues = (array, index0, index1, left, right) => {

  if (left === null) left = right;
  if (right === null) right = left;
  if (left === null && right === null) left = right = 0;

  let n = index1 - index0 + 1;
  let step = (right - left) / (n + 1);
  for (let i = 0; i < n; i++) {
    array[index0 + i] = left + step * (i + 1);
  }

}

const findZerosSequences = (array) => {

  var counter = 0;
  var index = 0;
  var result = [];

  for (let i = 0; i < array.length; i++) {
    if (array[i] === 0) {
      index = i;
      counter++;
    } else {
      if (counter !== 0) {
        result.push([index - counter + 1, index]);
        counter = 0;
      }
    }
  }

  if (counter !== 0) {
    result.push([index - counter + 1, index]);
  }

  return result;
}

let zeroes = findZerosSequences(sequence);

for (let i = 0; i < zeroes.length; i++) {
  let lf = zeroes[i][0] - 1 >= 0 ? sequence[zeroes[i][0] - 1] : null;
  let rf = zeroes[i][1] + 1 < sequence.length ? sequence[zeroes[i][1] + 1] : null;
  interpolateValues(sequence, zeroes[i][0], zeroes[i][1], lf, rf);
}

console.log(sequence);

Answer №2

If you're craving spaghetti instead of a proper response :)

const sequence = [
    0, 0, 0, 0, 0,
    12, 64, 9, 6,
    0, 0, 0, 
    25, 79, 57, 13, 39,
    0, 0,
    7, 7,
    0, 0, 0, 0, 0,
    49,
    0
]

const output = sequence.join(',')
.replace(/^([0,]+)(\d+)/, (_, zeros, number) => {
  const n = zeros.match(/0/g).length
  return (number + ',').repeat(n) + number
})
.replace(/([^0,]+),([0,]+)([^0,]+)/g, (_, number1, zeros, number2) => {
  const n = zeros.match(/0/g).length
  const diff = +number2 - +number1
  const step = diff / (n + 1)
  return number1 + ',' + [...Array(n).keys()].map(i => {
    const val = +number1 + (i + 1) * step
    return Math.floor(val * 10000) / 10000
  }) + ',' + number2
})
.replace(/(\d+)([,0]+)$/, (_, number, zeros) => {
  const n = zeros.match(/0/g).length
  return number + (',' + number).repeat(n)
}).split(',').map(Number);

console.log(output)

Answer №3

One way to keep track of start and end values when looping over to find non-zero values is by setting the starting index as -1 at the beginning. If the index is not set at the start, you know it needs to be the first value. The loop can run one extra index to determine the end value. For all other cases, the calculation will follow the step-wise process.

let sequence = [
    0, 0, 0, 0, 0,
    12, 64, 9, 6,
    0, 0, 0, 
    25, 79, 57, 13, 39,
    0, 0,
    7, 7,
    0, 0, 0, 0, 0,
    49,
    0
]; 

let startIndex = -1;

for (var i = 0; i <= sequence.length; i++) {

if (sequence[i] !== 0) {
    if (i - startIndex > 1) {

      let func;
      const startVal = sequence[startIndex];
      const endVal = sequence[i];

      if (startIndex === -1) {
        func = () => endVal;
      } else if (i === sequence.length) {
        func = () => startVal;
      } else {
        func = (j) => {
            return startVal + (endVal - startVal) / (i - startIndex) * j;
        }
      }

      for (let j = 1; j < i - startIndex; j++) {
        sequence[j + startIndex] = func(j);
      }
    }
    
    startIndex = i;
  }
}

console.log(sequence);

Another approach is to set the start and end values beforehand and then perform the necessary calculations during the loop.

let sequence = [
    0, 0, 0, 0, 0,
    12, 64, 9, 6,
    0, 0, 0, 
    25, 79, 57, 13, 39,
    0, 0,
    7, 7,
    0, 0, 0, 0, 0,
    49,
    0
]; 

let startIndex = -1;
for (var i = 0; i <= sequence.length; i++) {

  if (sequence[i] !== 0) {
    if (i - startIndex > 1) {

      const startVal = startIndex === -1 ? sequence[i] : sequence[startIndex];
      const endVal = i === sequence.length ? startVal : sequence[i];

      const func = (j) => {
        return startVal + (endVal - startVal) / (i - startIndex) * j;
      }

      for (let j = 1; j < i - startIndex; j++) {
        sequence[j + startIndex] = func(j);
      }
    }

    startIndex = i;
  }
}

console.log(sequence);

Answer №4

I haven't reviewed my test yet, but you might want to check out how I make educated guesses...

    const set = [
   0, 0, 0, 0, 0,
   12, 64, 9, 6,
   0, 0, 0,
   25, 79, 57, 13, 39,
   0, 0,
   7, 7,
   0, 0, 0, 0, 0,
   49,
   0
];
let tempZerosArr = [];
for (const [i, val] of set.entries()) {
   if (val) {
      if (!tempZerosArr.length) continue;
      tempZerosArr.splice(0, tempZerosArr.length - 2);
      let [first, second] = tempZerosArr;
      let leftVal = set[first-1];
      let rightVal = set[second+1];
      if (
         (!!leftVal && leftVal > 0) &&
         (!!rightVal && rightVal > 0)
      ) interpolateValues(set, first, second, leftVal, rightVal);
      tempZerosArr = [];
      continue;
   }
   tempZerosArr.push(i);
}

Answer №5

Below is a solution that takes in an input array and produces an interpolated output array. I have included comments within the code to clarify its functionality. This solution is capable of handling arrays consisting entirely of zeros.

function interpolateArray(input) {
    let output = []; // Array to store output values
    let zeros = 0; // Count of consecutive zeros
    let start = 0; // Initial value for interpolation
    for (let i = 0; i < input.length; i++) { // Iterate through all input values
        let value = input[i]; // Current input value
        if (value === 0) zeros++; // Increment zero count if the value is zero
        else { // For non-zero values...
            if (start === 0) start = value; // Update start with current non-zero value if initial
            if (zeros) { // If there are accumulated zeros...
                let step = (value - start) / (zeros + 1); // Calculate step size (difference between current value and start divided by total steps)
                for (let j = 1; j <= zeros; j++) output.push(start + (j * step)); // Push interpolated values to output for each zero
                zeros = 0; // Reset zero count
            }
            start = value; // Store current value as new start
            output.push(start); // Add non-zero value to output
        }
    }
    for (let j = 0; j < zeros; j++) output.push(start); // Append last non-zero value for trailing zeros
    return output; // Return the final output array
}

Update:

I've optimized the code slightly for brevity while maintaining identical functionality.

function interpolateArray(input) {
    let output = [], zeros = 0, start = 0;
    input.forEach(value => {
        if (value) {
            start = start || value;
            if (zeros) {
                let step = (value - start) / (zeros + 1);
                while (zeros--) output.push(start += step);
                zeros = 0;
            }
            output.push(start = value);
        } else zeros++;
    });
    while (zeros--) output.push(start);
    return output;
}

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

Deploying a pair of GitHub repositories to a unified Azure web application

Although this isn't exactly a technical question, I couldn't find a more appropriate stackexchange site for it. Recently, I made the move to Azure for deploying my backend web applications and APIs. I discovered that it's possible to deploy ...

Guide: Using jQueryUI's explode effect to animate an HTML element explosion

I'm having trouble getting the jQueryUI explode effect to work properly. I've tested it out on this jsfiddle, but the explosion effect doesn't seem to happen as expected - the element just disappears with no explosion animation. $('h1, ...

Creating a dynamic navbar with Python (Django), HTML, CSS, and Javascript for a fully responsive

I am currently utilizing a guideline to develop a responsive navbar that adapts its layout based on the screen size. It will display elements in a dropdown list for smaller screens, as opposed to an inline layout used for larger screens. Here is a snippet ...

Receiving undefined when trying to access an array within the state in React

When I use console.log(this.state.animal_names), the output is >(2) [Array(2), Array(2)] Upon expanding, I see 0: (2) ["dogNames", Array(53)] 1: (2) ["catNames", Array(100)] However, when I attempt to access them like this: desiredAnimal = "dogNames ...

Dropdown menu of countries created with Material UI

I have been working on creating a dropdown menu in my form that lists all countries. I used an Array of strings with country names and mapped through it to generate the options for the select dropdown. However, the dropdown menu does not seem to be worki ...

HTML, JavaScript, and PHP elements combine to create interactive radio buttons that trigger the appearance and disappearance of mod

On my page, I have multiple foreach loops generating divs with different information. These divs are displayed in modals using Bootstrap. However, I am encountering an issue where if I select a radio button and then close the modal and open another one, th ...

Using Three.js to import and cast rays on a .obj model created in Blender

I have successfully imported a 3D terrain using Blender and the OBJLoader in Three.js. In addition, I have created a mesh (highlighted in yellow in the image below) that I want to follow the mouse cursor while it hovers over the terrain. I have attempted t ...

What is the process for exporting all sub-module types into a custom namespace?

When we import all types from a module using a custom-namespace, it appears to work smoothly, for example: import * as MyCustomNamespace from './my-sub-module' We are also able to export all types from a module without creating a new namespace, ...

In React JS, the material-ui Accordion component's onchange function is failing to retrieve the current value

I am encountering an issue with the @material-ui Accordion where the onChange function is not capturing the current value. For example, when I click on the panel1 icon, it opens panel2 instead of taking the current value on icon click. I have provided the ...

Send Components to another component without specific TypeScript typespecified

Struggling with a situation where I am faced with the challenge of working around strongly typed variables. The issue arises with a set of icons as components and an icon wrapper component. The wrapper component requires a themeMode variable to determine ...

Difficulty in altering the background of an input box

I am attempting to design a textbox that changes its background color to green when the correct answer is submitted, and to red for an incorrect answer. Unfortunately, nothing is happening for either option. document.querySelector('form').addE ...

Sorting by a nested object property in Angular using OrderBy

I have created a table... <table width="100%"> <thead> <tr ng-repeat="row in data.Rows | limitTo:1"> <th ng-repeat="col in row.Columns" ng-show="{{col.Visible}}" ng-click="updateSortOrder(col.Header ...

How can you define index boundaries to access multiple items in JavaScript with ease?

Before diving into JavaScript, my main expertise was in R. In R, I used to access multiple items in an array using items[1:66], which would gather all items from 1 to 66 by using the : notation. I'm curious to know what is the equivalent method in Ja ...

Using property binding in Angular 8 can cause the image source for an SVG file to malfunction

In my component, I have an array that looks like this: this.myArray = [ { img: '/path/to/myImage.svg', title: 'My Image' } ] I'm using this array in the template to create a list: <div *n ...

Structure: Divergent Routes

I have been developing a form for my job, using some code I found online. The form starts by asking a simple question: Does the student have an ID? The answer is toggled between "YES" and "NO". If "Yes" is selected, the form will retrieve student informati ...

Retrieving object keys in Node.js based on their values

Wanting to create a function in nodejs 8.10 that returns a different object based on parameters provided, is there an easy way to include or exclude a key based on its value? For instance: // The current solution which can be improved // `c` might be und ...

Encountering difficulties retrieving information from an API using Angular

I am encountering an issue while trying to retrieve data from an API. When I use console.log() to view the data, it shows up in the console without any problem. However, when I attempt to display this data in a table, I keep receiving the error message: ER ...

Having a custom getter in a Response DTO does not function properly

After attempting to create a custom getter as shown below: import { Expose } from 'class-transformer'; export class MyDTOResponse { @Expose() id: string; @Expose() name: string; @Expose() get thisIsATest(): string { return &apo ...

What is the best way to incorporate Electron browser windows within Angular-CLI components?

How can I use electron browser window inside components in angular-cli if it doesn't accept it? I encountered an error with fs.existsync. Are there any alternative options to integrate electron with angular2 components? var electron = require(&apos ...

What is the process for checking the selected option, retrieving an array value, and displaying it in a div by clicking a button?

The query may seem a bit unclear, but I will do my best to explain. Here is the HTML code snippet: <div id="buttonholder"> <button id="previous">< Previous round</button> <button id="next">Next round ></button> ...