Home > Back-end >  Javascript: Interpolate zeroes sequences in a number array
Javascript: Interpolate zeroes sequences in a number array

Time:08-27

let's say I have an arbitrary number sequence

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
  
]; 

I need to replace all zeroes with interpolation given from non-zeroes neighbours, so the output would be

let output = [
  
    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
  
];

While firs zeroes [0, 4] doesn't have left neighbour all their values have to be 12, while last zero has only right resident 49, it would be just 49.

For me, it doesn't really a problem to fill parts where both left and right neighbours are presented, however I'm looking for an universal and elegant solution for this task.

const interpolateValues = (array, index0, index1, left, right) => {
    
   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 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
  
];
   
//[[0,4], [9, 11], [17, 18], [21, 25], [27, 27]]
let zeroes = findZerosSequences(sequence);
    
for(let i = 0; i < zeroes.length; i  ){
    
    let lf = sequence[zeroes[i][0] - 1];
    let rf = sequence[zeroes[i][1]   1];
        
    if(lf !== undefined && rf !== undefined && lf > 0 && rf > 0){
        
        interpolateValues(sequence, zeroes[i][0], zeroes[i][1], lf, rf);
        
    }
    
}

console.log(sequence);
        
let output = [
  
    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
  
];

CodePudding user response:

You almost got it, let the interpolateValues worry about those edge cases which are easily resolved.

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);

CodePudding user response:

I would keep track of the start and end values when looping over looking for non zeros. When it is the start the starting index will not be set so you know it needs to be the first value. You can loop one extra index and you know it will be the end. For the others it will be the step like you did.

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);

Other way is set the start and end and do the calculation

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);

CodePudding user response:

Haven't checked my sample, but you should see the way I guess..

    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 temporaryZerosArray = [];
for (const [id, value] of sequence.entries()) {
   if (value) {
      if (!temporaryZerosArray.length) continue;
      temporaryZerosArray.splice(0, temporaryZerosArray.length - 2);
      let [one, two] = temporaryZerosArray;
      let lf = sequence[one-1]
      let rf = sequence[two 1]
      if (
         (!!lf && lf > 0) &&
         (!!rf && rf > 0)
      ) interpolateValues(sequence, one,two, lf , rf );
      temporaryZerosArray = [];
      continue
   }
   temporaryZerosArray.push(id);
}
  • Related