我正在尝试在forEach
循环中删除数组中的元素,但我遇到了我已经看过的标准解决方案的问题。
这就是我目前正在尝试的事情:
review.forEach(function(p){
if(p === '\u2022 \u2022 \u2022'){
console.log('YippeeeE!!!!!!!!!!!!!!!!')
review.splice(p, 1);
}
});
我知道它已进入if
,因为我在控制台中看到了YippeeeeeE!!!!!!!!!!!!!
。
我的问题:我知道我的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语句,但显而易见的是[•••]仍在那里。
答案 0 :(得分:184)
看起来你正试图这样做?
使用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 while,但如果愿意,可以使用for糖
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 and 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
为false。但是我们将在解决方案中忽略它,因为它是另一个未指明的边缘情况。
所以我们有它,一个更完整的答案,解决方案仍然有边缘情况。第一个代码示例仍然是正确的,但如上所述,它并非没有问题。
答案 1 :(得分:22)
使用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);
答案 2 :(得分:7)
尽管Xotic750's answer提供了一些优点和可能的解决方案,有时simple is better。
您知道要迭代的数组在迭代本身中就已经发生了变异(即删除项=>索引更改),因此最简单的逻辑是在老式的 for
中倒退strong>(是 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
循环的语法糖...因此,如果它对您没有帮助,请停止破坏您的反对它。
答案 3 :(得分:1)
您也可以使用indexOf来执行此操作
var i = review.indexOf('\u2022 \u2022 \u2022');
if (i !== -1) review.splice(i,1);
答案 4 :(得分: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);
答案 5 :(得分:0)
您应该如何做到这一点:
review.forEach(function(p,index,object){
if(review[index] === '\u2022 \u2022 \u2022'){
console.log('YippeeeE!!!!!!!!!!!!!!!!')
review.splice(index, 1);
}
});
答案 6 :(得分:0)
以下内容将为您提供与您的特殊字符不同的所有元素!
review = jQuery.grep( review, function ( value ) {
return ( value !== '\u2022 \u2022 \u2022' );
} );