如何删除每个循环中的数组元素?

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

271643 次浏览

你应该这样做:

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

你也可以使用 indexOf 来代替

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

看起来你想这么做?

使用 < a href = “ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global _ Objects/Array/splice”rel = “ norefrer”> 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>

Which works fine for simple case where you do not have 2 of the same values as adjacent array items, other wise you have this problem.

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>

So what can we do about this problem when iterating and mutating an array? Well the usual solution is to work in reverse. Using ES3 while but you could use for sugar if preferred

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>

Ok, but you wanted to use ES5 iteration methods. Well and option would be to use Array.prototype.filter but this does not mutate the original array but creates a new one, so while you can get the correct answer it is not what you appear to have specified.

We could also use ES5 Array.prototype.reduceRight, not for its reducing property by rather its iteration property, i.e. iterate in 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.reduceRight(function(acc, item, index, object) {
if (item === 'a') {
object.splice(index, 1);
}
}, []);


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

Or we could use ES5 Array.protoype.indexOf like so.

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>

But you specifically want to use ES5 Array.prototype.forEach, so what can we do? Well we need to use Array.prototype.slice to make a shallow copy of the array and Array.prototype.reverse so we can work in reverse to mutate the original array.

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>

Finally ES6 offers us some further alternatives, where we do not need to make shallow copies and reverse them. Notably we can use Generators and Iterators. However support is fairly low at present.

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>

Something to note in all of the above is that, if you were stripping NaN from the array then comparing with equals is not going to work because in Javascript NaN === NaN is false. But we are going to ignore that in the solutions as it it yet another unspecified edge case.

So there we have it, a more complete answer with solutions that still have edge cases. The very first code example is still correct but as stated, it is not without issues.

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

下面将给出所有不等于您的特殊字符的元素!

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

我理解您希望使用一个条件从数组中删除,并使用另一个从数组中删除项的数组。对吗?

这个怎么样?

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”和“ for each”进行了比较。

如果在字符串包含“ 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);

尽管 Xotic750的回答提供了一些好的观点和可能的解决方案,有时候是 简单更好

你知道被迭代的数组在迭代过程中发生了变化(比如删除一个条目 = > 索引变化) ,因此最简单的逻辑就是用一种老式的 for语言(比如 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循环的句法糖... ... 所以如果它没有帮助你,请不要再用头去撞它了。

我在下面的代码中遇到了问题。接下来是我的解决方案。首先,问题在于: 假设您想修剪字符串,并丢弃字符串中带有“ 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”永远不会被修剪。它保留在审查数组中,前面和后面都有空格。

enter image description here

这是因为您扰乱了 foreach 所构建的审查数组。最好是复制一个数组,将可以保留的元素放入其中,并跳过不可以保留的元素。然后,输出新的 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);

正如你所看到的,这个方法非常有效:

enter image description here