Javascript拼接方法中的怪异错误

时间:2019-06-30 18:59:56

标签: javascript algorithm sorting array-algorithms

我有一个包含“零”的数组,我想移动所有 数组的最后一个索引的“零”。

预期输出为:

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

但是我得到了:

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

let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;

for (i = 0; i < len; i++) {
  if (a[i] == 0) {
    count = count + 1;
    a.splice(i, 1);
  }
}

for (j = 0; j < count; j++) {
  a.push(0);
}

console.log(a);

7 个答案:

答案 0 :(得分:9)

当您从数组中删除该项目时,所有元素都会下移一个。前进索引(i ++)时,将跳过数组中向下移动的项,该项在数组中恰好是连续的零。

解决方案:向后进行for next循环,它将起作用。

答案 1 :(得分:4)

由于剪接会更改数组的长度,因此您可以从数组的末尾进行迭代,然后将找到的值直接剪接到最后一个索引。

使用这种方法,您只需要一个循环。

var a = [0, 1, 2, 0, 0, 3, 0],
    i = a.length;

while (i--) {
    if (a[i] === 0) {
        a.splice(a.length, 0, ...a.splice(i, 1));
    }
}

console.log(a);

一种不进行拼接的较短方法-从零开始。

var a = [0, 1, 2, 0, 0, 3, 0],
    i, j = 0;

for (i = 0; i < a.length; i++) {
    if (a[i] !== 0) {
        [a[j], a[i]] = [a[i], a[j]]; // swap
        j++;
    }        
}

console.log(a);

答案 2 :(得分:1)

您可以使用Array.prototype.sort()来简化它:

const array = [0, 1, 2, 0, 0, 3, 0];
const sortedArray = array.sort((a, b) => {
  if (a === 0) {
    return 1;
  }
  if (b === 0) {
    return -1;
  }
  return a - b;
});

console.log(sortedArray);

答案 3 :(得分:1)

在for循环中,对数组进行拼接时,数组及其长度都会更改。

为此,您必须通过减去1来固定i在for循环中

  i++;

并通过减去1来固定长度,或者再次获取长度

let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;

for (i = 0; i < len; i++) {
  if (a[i] == 0) {
    count = count + 1;
    a.splice(i, 1);
    len = a.length;
    i--;
  }
}

for (j = 0; j < count; j++) {
  a.push(0);
}

console.log(a);

答案 4 :(得分:0)

每次使用接头时,您可以添加i--;len--;

let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;

for (i = 0; i < len; i++) {
  if (a[i] == 0) {
    count = count + 1;
    a.splice(i, 1);
    i--; len--;
  }
}

for (j = 0; j < count; j++) {
  a.push(0);
}

console.log(a);

这是因为在拼接1个元素时,数组的键向下移动了一个,因此要检查的下一个元素的键与刚删除的元素相同。 len也可以通过len--;进行校正,因为我们只是删除了一个元素。

虽然此答案是使用原始计划执行此操作的正确方法,但它可以解决。您的问题是您遍历了一个数组,并且该数组在循环中丢失了元素,通常在这种情况下,正确的方法是向后循环。这样,可能会在循环中更改其密钥的元素就是我们已经检查过的元素。

答案 5 :(得分:0)

请注意,对splice每个调用通常具有O(n) complexity。有很多方法可以通过一次O(n)迭代来更有效地获得所需的结果一个数量级。这是一个:

let a = [0, 1, 2, 0, 0, 3, 0]

for (let i=0, j=0; j<a.length; j++)
  if (a[j] && i != j)
    [a[i++], a[j]] = [a[j], 0]

console.log(a)

答案 6 :(得分:0)

不是一遍又一遍地拼接数组,而是一种不同的方法:

let a = [0, 1, 2, 0, 0, 3, 0];
// create some more (random) data
for (let i = a.length; i < 30; ++i)
  a[i] = Math.floor(Math.random() * Math.random() * 10);
console.log(""+a);

let i = 0, j = 0, len = a.length;
// move non-0 values to the front
while (i < len) {
  if (a[i] !== 0) {
    a[j++] = a[i];
  }
  ++i;
}
// fill the end of the list with 0
while (j < len) a[j++] = 0;

console.log(""+a);