Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 删除前一个元素时,forEach跳过该元素_Javascript_Performance - Fatal编程技术网

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);
});