簡體   English   中英

如何從 forEach 循環中的數組中刪除元素?

[英]How to remove element from array in forEach loop?

我試圖在forEach循環中刪除數組中的一個元素,但我遇到了我見過的標准解決方案的問題。

這是我目前正在嘗試的:

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

我知道它進入了if因為我看到了YippeeeeeE!!!!!!!!!!!!! 在控制台中。

我的問題:我知道我的 for 循環和 if 邏輯是正確的,但是我試圖從數組中刪除當前元素的嘗試失敗了。

更新:

嘗試了 Xotic750 的答案,但該元素仍未被刪除:

這是我的代碼中的 function:

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

這是數組仍未刪除的 output:

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

所以很明顯它按照指示進入 if 語句,但也很明顯 [• • •] 仍然存在。

看起來您正在嘗試這樣做?

使用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 為我們提供了一些進一步的選擇,我們不需要制作淺拷貝和反轉它們。 值得注意的是,我們可以使用Generators 和 Iterators 然而,目前支持率相當低。

 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是假的。 但是我們將在解決方案中忽略它,因為它是另一個未指定的邊緣情況。

所以我們有了它,一個更完整的答案,解決方案仍然存在邊緣情況。 第一個代碼示例仍然是正確的,但如前所述,它並非沒有問題。

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

盡管Xotic750 的回答提供了幾個優點和可能的解決方案,但有時簡單更好

您知道正在迭代的數組在迭代本身中發生了變化(即刪除項目 => 索引更改),因此最簡單的邏輯是在老式for (à la C語言)中倒退:

 let arr = ['a', 'a', 'b', 'c', 'b', 'a', 'a']; for (let i = arr.length - 1; i >= 0; i--) { if (arr[i] === 'a') { arr.splice(i, 1); } } document.body.append(arr.join());

如果您真的考慮一下, forEach只是for循環的語法糖……所以如果它對您沒有幫助,請停止反對它。

您也可以使用 indexOf 來代替執行此操作

var i = review.indexOf('\u2022 \u2022 \u2022');
if (i !== -1) review.splice(i,1);

我知道您想使用條件從數組中刪除並擁有另一個從數組中刪除項目的數組。 是對的?

這個怎么樣?

 var review = ['a', 'b', 'c', 'ab', 'bc']; var filtered = []; for(var i=0; i < review.length;) { if(review[i].charAt(0) == 'a') { filtered.push(review.splice(i,1)[0]); }else{ i++; } } console.log("review", review); console.log("filtered", filtered);

希望這有助於...

順便說一下,我將“for-loop”與“forEach”進行了比較。

如果在字符串包含 'f' 的情況下刪除,則結果不同。

 var review = ["of", "concat", "copyWithin", "entries", "every", "fill", "filter", "find", "findIndex", "flatMap", "flatten", "forEach", "includes", "indexOf", "join", "keys", "lastIndexOf", "map", "pop", "push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "toLocaleString", "toSource", "toString", "unshift", "values"]; var filtered = []; for(var i=0; i < review.length;) { if( review[i].includes('f')) { filtered.push(review.splice(i,1)[0]); }else { i++; } } console.log("review", review); console.log("filtered", filtered); /** * review [ "concat", "copyWithin", "entries", "every", "includes", "join", "keys", "map", "pop", "push", "reduce", "reduceRight", "reverse", "slice", "some", "sort", "splice", "toLocaleString", "toSource", "toString", "values"] */ console.log("========================================================"); review = ["of", "concat", "copyWithin", "entries", "every", "fill", "filter", "find", "findIndex", "flatMap", "flatten", "forEach", "includes", "indexOf", "join", "keys", "lastIndexOf", "map", "pop", "push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "toLocaleString", "toSource", "toString", "unshift", "values"]; filtered = []; review.forEach(function(item,i, object) { if( item.includes('f')) { filtered.push(object.splice(i,1)[0]); } }); console.log("-----------------------------------------"); console.log("review", review); console.log("filtered", filtered); /** * review [ "concat", "copyWithin", "entries", "every", "filter", "findIndex", "flatten", "includes", "join", "keys", "map", "pop", "push", "reduce", "reduceRight", "reverse", "slice", "some", "sort", "splice", "toLocaleString", "toSource", "toString", "values"] */

並且每次迭代刪除,結果也不同。

 var review = ["of", "concat", "copyWithin", "entries", "every", "fill", "filter", "find", "findIndex", "flatMap", "flatten", "forEach", "includes", "indexOf", "join", "keys", "lastIndexOf", "map", "pop", "push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "toLocaleString", "toSource", "toString", "unshift", "values"]; var filtered = []; for(var i=0; i < review.length;) { filtered.push(review.splice(i,1)[0]); } console.log("review", review); console.log("filtered", filtered); console.log("========================================================"); review = ["of", "concat", "copyWithin", "entries", "every", "fill", "filter", "find", "findIndex", "flatMap", "flatten", "forEach", "includes", "indexOf", "join", "keys", "lastIndexOf", "map", "pop", "push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "toLocaleString", "toSource", "toString", "unshift", "values"]; filtered = []; review.forEach(function(item,i, object) { filtered.push(object.splice(i,1)[0]); }); console.log("-----------------------------------------"); console.log("review", review); console.log("filtered", filtered);

以下是您應該如何操作:

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

以下將為您提供所有不等於您的特殊字符的元素!

review = jQuery.grep( review, function ( value ) {
    return ( value !== '\u2022 \u2022 \u2022' );
} );

我在使用以下代碼時遇到問題。 我的解決方案如下。 首先是問題:假設您要修剪字符串,並丟棄其中帶有“c”的字符串:

 var review = [' a ', ' b ', ' c ', ' d ', ' e ']; review.forEach(function(item, index) { review[index] = item.trim(); console.log("After trimming, the item is ", review[index]); if (review[index] === 'c') { review.splice(index, 1); } }); console.log("Review is now: "); console.log(review);

如果你運行上面的代碼,你會看到 'd' 永遠不會被修剪。 它保留在評論數組中,前后都有空格。

在此處輸入圖像描述

那是因為你弄亂了構建 foreach 的審查數組。 最好復制數組,然后將可以保留的元素推入其中,並跳過不保留的元素。 然后,output 新的 FinalArray,如下所示:

 var review = [' a ', ' b ', ' c ', ' d ', ' e ']; var finalArray = []; review.forEach(function(item, index) { // Add it to the new array first. If it turns out to be bad, remove it before going onto // the next iteration. finalArray.push(item.trim()); console.log("After trimming, the item is ", item.trim()); if (item.trim() == 'c') { // skip c finalArray.pop(); // This way, removing it doesn't affect the original array. } }); console.log("FinalArray is now: "); console.log(finalArray);

如您所見,這非常有效:

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM