For 循环不遍历整个数组 (Javascript)

For loop not iterating through whole array (Javascript)

我正在尝试解决一个问题,该问题采用数组并将所有零移动到末尾,同时保留其他元素的顺序。

这并没有遍历整个数组,如果您对我做错了什么有任何想法,我们将不胜感激。

let moveZeros = function (arr) {
  let newArr = [];
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] === 0) {
      newArr.push(arr[i]);
      arr.splice(i, 1);
    }
  }
  return arr.concat(newArr);
};

moveZeros([9, 0, 9, 1, 2, 1, 1, 3, 1, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0]);

// expexted to return [9,9,1,2,1,1,3,1,9,9,0,0,0,0,0,0,0,0,0,0]
// currently returns  [9,9,1,2,1,1,3,1,9,0,9,0,0,0,0,0,0,0,0,0]

// Strangely... sending a smaller array to the function seems to work.

//moveZeros([false,1,0,1,2,0,1,3,"a"])
// correctly returns[false,1,1,2,1,3,"a",0,0]

这个问题与长度无关,当你有多个连续的0时就会出现问题。例如[0,0,9,0,0,9]会出现[0,9,0 ,9,0,0].

在循环的第一次迭代 (i=0) 中,您从数组中删除第一个 0,留下 [0,9,0,0,9]。在第二次迭代 (i=1) 中,它现在查看数组中的第二个元素,即 9。第一个 0 被跳过。随着循环的进行,这也会在稍后的数组中发生。

一般来说,在遍历数组时修改数组可能会出现问题。有多种方法可以执行这样的排序。但要使其接近原始版本,您可以这样做:

let moveZeros = function(arr) {
    let arrA = [];
    let arrB = [];
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] === 0) {
            arrB.push(arr[i]);
        } else {
            arrA.push(arr[i]);
        }
    }
    return arrA.concat(arrB);
};

现在函数在遍历原始数组时保持原样。非 0 项被推送到 arrA,0 被推送到 arrB,然后将这两者连接起来。

您可以保留数组并将所有非零值移动到开头并用零填充其余值。

let moveZeros = function(array) {
        let i = 0,
            j = 0;

        while (i < array.length) {
            if (array[i] !== 0) array[j++] = array[i];
            i++;
        }

        while (j < array.length) array[j++] = 0;

        return array;
    };

console.log(...moveZeros([9, 0, 9, 1, 2, 1, 1, 3, 1, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0]));
console.log(...moveZeros([false, 1, 0, 1, 2, 0, 1, 3, "a"]));