3

I'm trying to remove all the numbers from an array. The loop works exactly as I want, but the splice() method still skips some elements for some reason.

let arr = ['1', '2', '3', '4', '5', 'notanumber', '6'];

for (let element of arr) {
  let index = arr.indexOf(element);
  let check = isNaN(element);
  if (check === false) {
    arr.splice(index, 1);
  };
};

console.log(arr);

Expected output is: ['notanumber']
Current output is: ['2', '4', 'notanumber']

Calvin Nunes
  • 6,376
  • 4
  • 20
  • 48
Ilya Kozel
  • 51
  • 1
  • 3
  • You are simultaneously changing the array while you are looping thorough it – adiga Apr 10 '19 at 19:25
  • 1
    Possible duplicate of [Looping through array and removing items, without breaking for loop](https://stackoverflow.com/questions/9882284/looping-through-array-and-removing-items-without-breaking-for-loop) – adiga Apr 10 '19 at 19:25

4 Answers4

6

This would do

arr = arr.filter(x => isNaN(x));

The problem with calling splice for each element is that you're changing the array while iterating over it.

To do what filter does by hand the approach should be more like:

let wp = 0;
for (let i=0; i<arr.length; i++) {
    if (isNaN(arr[i])) arr[wp++] = arr[i];
}
arr.length = wp;

In other words you keep a "write pointer" wp and for each element of the array that you want to keep you move it in place, without moving subsequent elements that still need to be processed. Only at the end you resize the result. This is much faster (o(N) instead of o(N²)) and simpler to keep correct.

This second approach moreover will mutate the array inplace, filter instead will return a new array and this is different if other references to the array are present in the program.

6502
  • 112,025
  • 15
  • 165
  • 265
3

Use this as it uses a filter which is less code than a loop:

let arr = ['1', '2', '3', '4', '5', 'notanumber', '6'];
console.log(arr.filter(x => isNaN(x)))
VFDan
  • 831
  • 10
  • 26
2

Why not iterate from the end?

BTW, you need the index, because you search for an index with a value, this goes wrong, if you have more than one same value in the array.

Then you have the problem by iterating from start, because splicing makes, in this case, the array length shorter and the next index is the actual index.

let array = ['1', '2', '3', '4', '5', 'notanumber', '6'],
    i = array.length;

while (i--) {
    if (!isNaN(array[i])) array.splice(i, 1);
}

console.log(array);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

you can try to remove all the numbers like that

let arr = ['1', '2', '3', '4', '5', 'notanumber', '6'];
arr  = arr.filter( element=> isNaN(parseInt(element)) )
console.log(arr); //output is ['notanumber']

using the parseInt function in an element that is not number the return will be NaN

so we can use the filter to remove only the numbers

Jeferson Macedo
  • 695
  • 7
  • 11