使用for循环删除数组含'land'元素时Ireland漏删问题排查
问题根源
你这段代码的核心问题是正向遍历数组时调用splice删除元素会引发索引偏移,导致后续元素被跳过漏检:
- 调用
splice(i,1)删除索引i的元素后,i位置后方的所有元素会自动向前移动1位,原本在i+1位置的元素会补到i位置 - 但当前轮次判断结束后,循环变量
i会固定自增1,直接跳到i+1位置,就把刚补到i位置的元素完全跳过,没有做匹配检查 - 放到你的示例里推演:原数组中带"land"子串的元素共有3个,分别是索引5的
Finland、索引9的Iceland、索引10的Ireland- 当i=5时删除
Finland,后方元素整体前移,Iceland从索引9变到索引8,i自增到6后跳过了一轮检查 - 当i=8时检测到前移后的
Iceland并执行删除,后方的Ireland从索引9前移到索引8,i再次自增到9 - 此时数组长度因为两次删除已经变成9,判断
i < cntry.length即9 < 9结果为false,循环直接终止,根本没检查到已经移到索引8位置的Ireland,导致该元素残留。
- 当i=5时删除
符合for循环要求的修复方案
要求仅用for循环实现的话,有两种通用的正确写法:
方案1:倒序遍历数组
从数组最后一个元素往前遍历,此时删除元素只会影响已经遍历过的尾部元素,不会打乱还没检查的前部元素的索引,不会出现漏检:
const cntry = ['Albania', 'Bolivia', 'Canada', 'Denmark', 'Ethiopia', 'Finland', 'Germany', 'Hungary', 'Turkey', 'Iceland', 'Ireland']; for (let i = cntry.length - 1; i >= 0; i--) { if (cntry[i].includes('land')) { cntry.splice(i, 1); } } // 运行结果:['Albania', 'Bolivia', 'Canada', 'Denmark', 'Ethiopia', 'Germany', 'Hungary', 'Turkey']
方案2:正向遍历+删除后回退索引
保留正向遍历的逻辑,每次执行删除操作后把循环变量i减1,抵消splice带来的索引偏移,保证下一轮循环能检查到补位到当前i位置的元素:
const cntry = ['Albania', 'Bolivia', 'Canada', 'Denmark', 'Ethiopia', 'Finland', 'Germany', 'Hungary', 'Turkey', 'Iceland', 'Ireland']; for (let i = 0; i < cntry.length; i++) { if (cntry[i].includes('land')) { cntry.splice(i, 1); i--; // 抵消删除后的索引前移 } } // 运行结果和倒序遍历完全一致
内容的提问来源于stack exchange,提问作者Brandt
相关产品推荐
相关产品推荐

