如何从 forEach 循环中的数组中删除元素?

新手上路,请多包涵

我试图在 forEach 循环中删除数组中的一个元素,但我遇到了我见过的标准解决方案的问题。

这是我目前正在尝试的:

 review.forEach(function(p){
   if(p === '\u2022 \u2022 \u2022'){
      console.log('YippeeeE!!!!!!!!!!!!!!!!')
      review.splice(p, 1);
   }
});

我知道它正在进入 if 因为我在控制台中看到 YippeeeeeE!!!!!!!!!!!!!

我的问题: 我知道我的 for 循环和 if 逻辑是正确的,但是我试图从数组中删除当前元素的尝试失败了。

更新:

尝试了 Xotic750 的答案,但该元素仍未被删除:

这是我的代码中的函数:

 review.forEach(function (item, index, object) {
    if (item === '\u2022 \u2022 \u2022') {
       console.log('YippeeeE!!!!!!!!!!!!!!!!')
       object.splice(index, 1);
    }
    console.log('[' + item + ']');
});

这是仍未删除数组的输出:

 [Scott McNeil]
[reviewed 4 months ago]
[ Mitsubishi is AMAZING!!!]
YippeeeE!!!!!!!!!!!!!!!!
[• • •]

所以很明显它按照指示进入 if 语句,但也很明显 [• • •] 仍然存在。

原文由 novicePrgrmr 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.2k
2 个回答

看起来你正在尝试这样做?

使用 Array.prototype.splice 迭代和改变数组

 var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'b', 'c', 'b', 'a'];

review.forEach(function(item, index, object) {
  if (item === 'a') {
    object.splice(index, 1);
  }
});

log(review);
 <pre id="out"></pre>

对于没有两个与相邻数组项相同的值的简单情况,这很好用,否则你会遇到这个问题。

 var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'a', 'b', 'c', 'b', 'a', 'a'];

review.forEach(function(item, index, object) {
  if (item === 'a') {
    object.splice(index, 1);
  }
});

log(review);
 <pre id="out"></pre>

那么在迭代和改变数组时,我们能做些什么来解决这个问题呢?那么通常的解决方案是反向工作。使用 ES3 但如果愿意 您可以使用 sugar

 var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a' ,'a', 'b', 'c', 'b', 'a', 'a'],
  index = review.length - 1;

while (index >= 0) {
  if (review[index] === 'a') {
    review.splice(index, 1);
  }

  index -= 1;
}

log(review);
 <pre id="out"></pre>

好的,但是您想使用 ES5 迭代方法。好吧,选择是使用 Array.prototype.filter 但这不会改变原始数组而是创建一个新数组,因此虽然您可以获得正确答案,但它并不是您指定的内容。

我们也可以使用 ES5 Array.prototype.reduceRight ,而不是通过它的迭代属性来减少它的属性,即反向迭代。

 var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'a', 'b', 'c', 'b', 'a', 'a'];

review.reduceRight(function(acc, item, index, object) {
  if (item === 'a') {
    object.splice(index, 1);
  }
}, []);

log(review);
 <pre id="out"></pre>

或者我们可以像这样使用 ES5 Array.protoype.indexOf

 var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'a', 'b', 'c', 'b', 'a', 'a'],
  index = review.indexOf('a');

while (index !== -1) {
  review.splice(index, 1);
  index = review.indexOf('a');
}

log(review);
 <pre id="out"></pre>

但是你特别想用ES5 的 Array.prototype.forEach ,那怎么办呢?好吧,我们需要使用 Array.prototype.slice 来制作数组的浅表副本和 Array.prototype.reverse 以便我们可以反向工作以改变原始数组。

 var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'a', 'b', 'c', 'b', 'a', 'a'];

review.slice().reverse().forEach(function(item, index, object) {
  if (item === 'a') {
    review.splice(object.length - 1 - index, 1);
  }
});

log(review);
 <pre id="out"></pre>

最后,ES6 为我们提供了一些更进一步的选择,我们不需要制作浅拷贝和反转它们。值得注意的是,我们可以使用 生成器和迭代器。但是目前支持率相当低。

 var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

function* reverseKeys(arr) {
  var key = arr.length - 1;

  while (key >= 0) {
    yield key;
    key -= 1;
  }
}

var review = ['a', 'a', 'b', 'c', 'b', 'a', 'a'];

for (var index of reverseKeys(review)) {
  if (review[index] === 'a') {
    review.splice(index, 1);
  }
}

log(review);
 <pre id="out"></pre>

以上所有内容中需要注意的是,如果您从数组中剥离 NaN ,则与 equals 进行比较将不起作用,因为在 Javascript 中 NaN === NaN 为 false。但是我们将在解决方案中忽略它,因为它是另一个未指定的边缘情况。

所以我们有了它,一个更完整的答案,解决方案仍然有边缘案例。第一个代码示例仍然正确,但如前所述,它并非没有问题。

原文由 Xotic750 发布,翻译遵循 CC BY-SA 4.0 许可协议

使用 Array.prototype.filter 而不是 forEach

 var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'b', 'c', 'b', 'a', 'e'];
review = review.filter(item => item !== 'a');
log(review);

原文由 alemjerus 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题