Strange issue with the splice function in JavaScript

I have an array with multiple “Zeros” and I need to rearrange it so that all the “Zeros” are positioned at the end of the array.

The result that I am aiming for is:

[1,2,3,0,0,0,0]

However, the output I’m getting is:

[1,2,0,3,0,0,0]

Here’s my code snippet:

let numbers = [0, 1, 2, 0, 0, 3, 0];
let zeroCount = 0;
const totalLength = numbers.length;

for (let index = 0; index < totalLength; index++) {
  if (numbers[index] === 0) {
    zeroCount++;
    numbers.splice(index, 1);
    index--;
  }
}

for (let i = 0; i < zeroCount; i++) {
  numbers.push(0);
}

console.log(numbers);

Your splice operation is altering the array in place and causing shifts in index positions. This means each time you remove a zero, the remaining elements shift left, leading to skipped checks on subsequent elements. Instead of using splice within the loop, you can use a more straightforward approach: filter out the zeros and then add them back at the end of the array. An example implementation could be:

let numbers = [0, 1, 2, 0, 0, 3, 0];
let filteredNumbers = numbers.filter(number => number !== 0);
let zeroCount = numbers.length - filteredNumbers.length;
for (let i = 0; i < zeroCount; i++) {
  filteredNumbers.push(0);
}
console.log(filteredNumbers);

This will reliably place all zeros at the end, maintaining the intended order for other numbers.

From personal experience, you can benefit from using an extra array or counter approach to keep track of the non-zero and zero elements separately. Here’s a way I’d tackle it: go through the array once to collect all non-zeros, then push zeros based on the count collected. Here’s a simple illustration:

let numbers = [0, 1, 2, 0, 0, 3, 0];
let nonZeros = [];
let zeroCount = 0;

numbers.forEach(number => {
  if (number !== 0) {
    nonZeros.push(number);
  } else {
    zeroCount++;
  }
});

for (let i = 0; i < zeroCount; i++) {
  nonZeros.push(0);
}

console.log(nonZeros);

This method minimizes operations by ensuring you’re only iterating twice, which can be a bit more efficient in some scenarios.

you could try using the sort method too, funny enough it can work for this kind of task. something like numbers.sort((a, b) => a === 0 ? 1 : -1). it will move all zeros to the end by treating 0 as larger than any other number. give it a try!