user10192617
user10192617

Reputation:

Fill Array with last defined value if null until next defined value

I have this array:

const arr = [2, 4, 8, 12, 15, null, null, null, 18, 39, null, 49, null, null]

How can I update the null value in this array with the last defined value until the next defined value and stop if there is no more defined value at the end.

So it looks like this:

 const arr = [2, 4, 8, 12, 15, 15, 15, 15, 18, 39, 39, 49, null, null]

Upvotes: 1

Views: 775

Answers (4)

Nina Scholz
Nina Scholz

Reputation: 386560

You could look for the last valid value from the end and omit the change for indices greater or equal than the index.

This code changes the array. If wanted, you could map new value by using an additional variable for the last not null value.

var array = [2, 4, 8, 12, 15, null, null, null, 18, 39, null, 49, null, null],
    j = array.length;

while (array[--j] === null) ;

array.forEach((v, i, a) => {
    if (v === null && i < j) {
        a[i] = a[i - 1];
    }
});

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

New Array

var array = [2, 4, 8, 12, 15, null, null, null, 18, 39, null, 49, null, null],
    j = array.length,
    result;

while (array[--j] === null) ;

result = array.map((l => (v, i) => l = v === null && i < j ? l : v)());

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

Upvotes: 0

Mark
Mark

Reputation: 92440

You can do this by walking two pointers along the array. It's a pretty c-ish way to do it, but it should be fast and it allows for leaving the tail null values without jumping through hoops.

const arr = [ 2, 4, 8, 12, 15, null, null, null, 18, 39, null, 49, null, null]

for (let i=0, j=0; i < arr.length; i++){   
    if (arr[i] === null ) continue
    while(j<i) {                    // catch up to first pointer while filling in values
        arr[j] = arr[j-1] || null   // the null handles the case where the first value is null
        j++
    }
    j++
}
console.log(arr)

This will edit the array in place. It's not clear what should happen if the first value is null. This will just keep it null which seems moderately sensible.

If you want to fill in the end null values you can just change the test on the for loop to: j < arr.length to allow the second pointer to catch up.

Upvotes: 0

Ori Drori
Ori Drori

Reputation: 191976

You can use Array.reduce() chunk the array for groups of null, and group without null. Iterate the groups with Array.map(), and if a null group is not the first or the last, fill it with the number before it. Flatten by spreading into Array.concat():

const arr = [2, 4, 8, 12, 15, null, null, null, 18, 39, null, 49, null, null];

const result = [].concat(...arr
  .reduce((r, n, i, a) => {
    if (!i || (n === null) === (a[i - 1] !== null)) {
      r.push([]);
    }

    r[r.length - 1].push(n);

    return r;
  }, [])
  .map((n, i, a) => {
    if(i && i < a.length - 1 && n[0] === null) {
      return [...n].fill(a[i - 1][a[i - 1].length - 1]);
    }
    
    return n;
  }));


console.log(result);

Upvotes: 0

gr4viton
gr4viton

Reputation: 1514

Iterate through the array with map, or forEach. Always store the last visited value after the null check and reassign.

const arr = [2, 4, 8, 12, 15, null, null, null, 18, 39, null, 49, null, null];

function getFilledUpArray(array) {
    let lastDefinedElement;
    return array.map(element => {
        if (element === null) {
            element = lastDefinedElement; 
        }
        
        lastDefinedElement = element;
        return element;
    });    
}

console.log( getFilledUpArray(arr) );

Upvotes: 4

Related Questions