删除数组中匹配价格的对象需多次调用findPrice函数的问题
问题分析与解决方案
我一眼就看出问题出在你用forEach循环修改数组并手动调整索引的方式上——forEach的迭代机制根本不吃这一套!这也是为什么你需要多次点击才能删干净,大数据量下漏删的情况会更严重。
问题根源拆解
forEach循环里的i是每次迭代传入的局部参数副本,你手动写i--完全不会影响forEach内部的迭代计数器,下一次循环还是会按原始索引走。- 当你用
splice(i,1)删除当前元素后,数组后面的元素会整体前移一位,但forEach不会管这个变化,下一次依旧会取下一个索引值,直接跳过了前移到当前位置的元素,导致这些元素没被检查到,自然删不干净。
最优解决方案:用filter一步到位
filter是处理这种数组筛选场景的最佳选择,它会返回一个全新的符合条件的数组,代码简洁、可读性高,还完全不会有索引混乱的问题,大数据量下性能也更稳定:
findPrice() { // 只保留positionDetail中存在匹配priceSearch的对象 this.arrayOfObjects = this.arrayOfObjects.filter(data => { // some方法找到第一个匹配项就会停止遍历,比findIndex更高效 return data.positionDetail.some(item => item.price === this.priceSearch); }); }
备选方案:反向for循环手动删除
如果你更习惯手动操作数组的方式,那一定要用反向遍历的for循环——从数组末尾往前删,删除当前元素不会影响前面还没遍历到的元素索引:
findPrice() { // 从最后一位开始遍历,往前倒序检查 for (let i = this.arrayOfObjects.length - 1; i >= 0; i--) { const currentItem = this.arrayOfObjects[i]; const hasMatchedPrice = currentItem.positionDetail.some(item => item.price === this.priceSearch); if (!hasMatchedPrice) { this.arrayOfObjects.splice(i, 1); // 反向遍历不需要调整i,前面的元素索引不受当前删除操作影响 } } }
再说说你的原代码为什么无效
回头看你原来的代码,核心问题就在i--这一步:
findPrice() { this.arrayOfObjects.forEach( (data, i) => { let searchIfExist= data.positionsDetail.findIndex(index1 => index1.price === priceSearch); if (searchIfExist=== -1) { this.arrayOfObjects.splice( i, 1 ); i--; // 这里的i是forEach传入的局部变量,修改它对下一次迭代毫无作用! } }); }
forEach的回调函数里的i是每次迭代的独立变量,你修改它只会改变这个局部变量的值,不会影响forEach内部的迭代进度。每次splice后数组长度减1,但forEach还是会按原始数组的长度走完所有循环,导致大量前移的元素被跳过检查。
用上面的两种方法修改后,不管数据量大小,都能一次性删除所有不符合条件的对象,再也不需要多次点击按钮了。
内容的提问来源于stack exchange,提问作者tremenk
相关产品推荐
相关产品推荐

