Javascript 删除前一个元素时,forEach跳过该元素
我有两个数组,Javascript 删除前一个元素时,forEach跳过该元素,javascript,performance,Javascript,Performance,我有两个数组,可用的\u项和请求的\u项。我想从请求的\u项目中删除可用\u项目中缺少的元素。使用forEach显然不会给出预期的结果,因为即使删除一个元素,内部索引也会增加,而下一个元素将具有旧索引 下面是一个测试用例(也在中): 结果是: "will keep 0 5" "will remove 1 12" "will remove 2 30" "will remove 3 17" "Resulting request array is 5,49,90" 这将重复数万次,因此,如果使用库(
可用的\u项
和请求的\u项
。我想从请求的\u项目
中删除可用\u项目
中缺少的元素。使用forEach
显然不会给出预期的结果,因为即使删除一个元素,内部索引也会增加,而下一个元素将具有旧索引
下面是一个测试用例(也在中):
结果是:
"will keep 0 5"
"will remove 1 12"
"will remove 2 30"
"will remove 3 17"
"Resulting request array is 5,49,90"
这将重复数万次,因此,如果使用库(例如下划线)对性能产生负面影响,我希望避免使用库
所以,我的问题是,什么是最便宜的纠正方法?使用for循环并向后计数,这样就不会对索引产生问题
for(var i = requested_items.length - 1; i >= 0; i--) {
// your logic
}
它“感觉”很粗糙,但它确实起到了作用。规范:
范围是在forEach函数开始执行之前确定的-因此您正在调用i=[0..5]
。。。元素a[1],a[2]。。a[5]
值本身是在访问索引时确定的。因此,如果您删除a[1]
,然后跳到a[2]
,您就跳过了一个值!(在您的示例中,a[1]
将增加到49。)
规范的最后一个重要部分:删除的索引不会被访问,所以这是一个无声的警告。在现实的C++数组中,你会看到:<代码>索引4超出范围!索引5超出范围!'代码>
有趣的是,如果我是你,原则上我可能会避免在循环中修改这个数组。在其他编程语言中,forEach循环是并行执行的,索引的顺序不是一成不变的。。修改包含结构会导致未定义的行为。正如你从说明书中看到的,这里有点。。。呃,你不应该这样做,但如果你这样做的话会发生什么
我的解决方案是创建第三个阵列并使用它:
var found_items = [];
requested_items.forEach(function(v, i, a) {
if(available_items.indexOf(v) !== -1) {
found_items.push(v);
}
});
保持所选样式的一种令人难以置信的方法是每次删除元素时使用while()循环保持在同一索引上
requested_items.forEach(function(v, i, a) {
if(available_items.indexOf(v) == -1) {
console.log("will remove " + i + ' ' + v);
a.splice(i, 1);
while(available_items.indexOf(a[i]) === -1) {
console.log("will also remove " + i + ' ' + a[i]);
a.splice(i, 1);
}
} else console.log("will keep " + i + ' ' + v);
});
啊,这太难看了。为什么不使用
for(blah中的var i)
?如果我记得的话,这保证了循环之前存在的每个元素都至少被访问一次。从循环的末尾开始,向后运行。那么结果数组应该是什么呢?@elclars在这种情况下,它应该是[5]
。即使使用大数组,也比过滤器
更快:(至少在chrome中)+1有趣的秘密信息和替代方法。
requested_items.forEach(function(v, i, a) {
if(available_items.indexOf(v) == -1) {
console.log("will remove " + i + ' ' + v);
a.splice(i, 1);
while(available_items.indexOf(a[i]) === -1) {
console.log("will also remove " + i + ' ' + a[i]);
a.splice(i, 1);
}
} else console.log("will keep " + i + ' ' + v);
});