I am trying to remove an element in an array in a forEach
loop, but am having trouble with the standard solutions I've seen.
我试图在forEach循环中删除数组中的元素,但我遇到了我见过的标准解决方案的问题。
This is what I'm currently trying:
这就是我目前正在尝试的:
review.forEach(function(p){
if(p === '\u2022 \u2022 \u2022'){
console.log('YippeeeE!!!!!!!!!!!!!!!!')
review.splice(p, 1);
}
});
I know it's getting into the if
because I'm seeing YippeeeeeE!!!!!!!!!!!!!
in the console.
我知道它正在进入if,因为我看到了YippeeeeeE !!!!!!!!!!!!!在控制台中。
MY PROBLEM: I know that my for loop and if logic are sound, but my attempt to remove the current element from the array is failing.
我的问题:我知道我的for循环和逻辑是否合理,但是我尝试从数组中删除当前元素失败了。
UPDATE:
更新:
Tried out Xotic750's answer, and the element is still not being removed:
尝试了Xotic750的答案,该元素仍未被删除:
Here is the function in my code:
这是我的代码中的函数:
review.forEach(function (item, index, object) {
if (item === '\u2022 \u2022 \u2022') {
console.log('YippeeeE!!!!!!!!!!!!!!!!')
object.splice(index, 1);
}
console.log('[' + item + ']');
});
Here is the output where the array is still not removed:
以下是仍未删除数组的输出:
[Scott McNeil]
[reviewed 4 months ago]
[ Mitsubishi is AMAZING!!!]
YippeeeE!!!!!!!!!!!!!!!!
[• • •]
So obviously it is going into the if statement as directed, but it's also obvious that the [• • •] is still there.
所以很明显它会按照指示进入if语句,但显而易见的是[•••]仍然存在。
6 个解决方案
#1
132
It looks like you are trying to do this?
看起来你正试图这样做?
Iterate and mutate an array using Array.prototype.splice
使用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.
这对于简单的情况很好,你没有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>
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
那么在迭代和变异数组时我们可以对这个问题做些什么呢?通常的解决方案是反向工作。使用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>
Ok, but you wanted 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.
好的,但是你想要使用ES5迭代方法。好吧,选项是使用Array.prototype.filter,但这不会改变原始数组但会创建一个新数组,所以虽然你可以得到正确的答案,但它并不是你所指定的。
We could also use ES5 Array.prototype.reduceRight, not for its reducing property by rather its iteration property, i.e. iterate in reverse.
我们也可以使用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>
Or we could use ES5 Array.protoype.indexOf like so.
或者我们可以像这样使用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>
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.
但是你特别想使用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>
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.
最后,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>
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.
在上述所有内容中需要注意的是,如果你从数组中剥离NaN,那么与equals进行比较是行不通的,因为在Javascript中NaN === NaN是假的。但是我们将在解决方案中忽略它,因为它是另一个未指明的边缘情况。
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.
所以我们有了它,一个更完整的答案,解决方案仍然有边缘情况。第一个代码示例仍然是正确的,但如上所述,它并非没有问题。
#2
16
Use Array.prototype.filter
instead of forEach
:
使用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);
#3
1
You could also use indexOf instead to do this
您也可以使用indexOf来执行此操作
var i = review.indexOf('\u2022 \u2022 \u2022');
if (i !== -1) review.splice(i,1);
#4
1
I understood that you want to remove from the array using a condition and have another array that has items removed from the array. Is right?
我知道你想要使用一个条件从数组中删除,并有另一个数组从数组中删除项目。是对的?
How about this?
这个怎么样?
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);
Hope this help...
希望这有帮助......
By the way, I compared 'for-loop' to 'forEach'.
顺便说一句,我将'for-loop'与'forEach'进行了比较。
If remove in case a string contains 'f', a result is different.
如果在字符串包含'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"]
*/
And remove by each iteration, also a result is different.
并且每次迭代删除,结果也不同。
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);
#5
0
The following will give you all the elements which is not equal to your special characters!
以下内容将为您提供与您的特殊字符不同的所有元素!
review = jQuery.grep( review, function ( value ) {
return ( value !== '\u2022 \u2022 \u2022' );
} );
#6
0
Here is how you should do it:
这是你应该怎么做:
review.forEach(function(p,index,object){
if(review[index] === '\u2022 \u2022 \u2022'){
console.log('YippeeeE!!!!!!!!!!!!!!!!')
review.splice(index, 1);
}
});
#1
132
It looks like you are trying to do this?
看起来你正试图这样做?
Iterate and mutate an array using Array.prototype.splice
使用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.
这对于简单的情况很好,你没有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>
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
那么在迭代和变异数组时我们可以对这个问题做些什么呢?通常的解决方案是反向工作。使用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>
Ok, but you wanted 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.
好的,但是你想要使用ES5迭代方法。好吧,选项是使用Array.prototype.filter,但这不会改变原始数组但会创建一个新数组,所以虽然你可以得到正确的答案,但它并不是你所指定的。
We could also use ES5 Array.prototype.reduceRight, not for its reducing property by rather its iteration property, i.e. iterate in reverse.
我们也可以使用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>
Or we could use ES5 Array.protoype.indexOf like so.
或者我们可以像这样使用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>
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.
但是你特别想使用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>
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.
最后,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>
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.
在上述所有内容中需要注意的是,如果你从数组中剥离NaN,那么与equals进行比较是行不通的,因为在Javascript中NaN === NaN是假的。但是我们将在解决方案中忽略它,因为它是另一个未指明的边缘情况。
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.
所以我们有了它,一个更完整的答案,解决方案仍然有边缘情况。第一个代码示例仍然是正确的,但如上所述,它并非没有问题。
#2
16
Use Array.prototype.filter
instead of forEach
:
使用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);
#3
1
You could also use indexOf instead to do this
您也可以使用indexOf来执行此操作
var i = review.indexOf('\u2022 \u2022 \u2022');
if (i !== -1) review.splice(i,1);
#4
1
I understood that you want to remove from the array using a condition and have another array that has items removed from the array. Is right?
我知道你想要使用一个条件从数组中删除,并有另一个数组从数组中删除项目。是对的?
How about this?
这个怎么样?
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);
Hope this help...
希望这有帮助......
By the way, I compared 'for-loop' to 'forEach'.
顺便说一句,我将'for-loop'与'forEach'进行了比较。
If remove in case a string contains 'f', a result is different.
如果在字符串包含'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"]
*/
And remove by each iteration, also a result is different.
并且每次迭代删除,结果也不同。
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);
#5
0
The following will give you all the elements which is not equal to your special characters!
以下内容将为您提供与您的特殊字符不同的所有元素!
review = jQuery.grep( review, function ( value ) {
return ( value !== '\u2022 \u2022 \u2022' );
} );
#6
0
Here is how you should do it:
这是你应该怎么做:
review.forEach(function(p,index,object){
if(review[index] === '\u2022 \u2022 \u2022'){
console.log('YippeeeE!!!!!!!!!!!!!!!!')
review.splice(index, 1);
}
});