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

2022-08-30 03:07:57

我正在尝试在循环中删除数组中的元素,但在使用我所看到的标准解决方案时遇到问题。forEach

这是我目前正在尝试的:

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

我知道它正在进入,因为我在控制台中看到。ifYippeeeeeE!!!!!!!!!!!!!

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

更新:

尝试了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语句,但同样明显的是,[•••]仍然存在。


答案 1

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

使用 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>

这适用于没有2个与相邻数组项相同的值的简单情况,其他明智的做法是你有这个问题。

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但如果你愿意,你可以用

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

因此,我们有了它,一个更完整的答案,其中包含仍然具有边缘情况的解决方案。第一个代码示例仍然是正确的,但如前所述,它并非没有问题。


答案 2

使用代替 :Array.prototype.filterforEach

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);