从循环中使用splice方法带来的问题,发现for循环真好

13 篇文章 0 订阅

需求:删除[1,2,3,4,5]中大于等于2小于5的项。(在业务场景中也是再常见不过了)

结果:[1,5]

当使用for:

let a = [1, 2, 3, 4, 5];
for (var i = 0; i < a.length; i++) {
   if (a[i] >= 2 && a[i] < 5) {
      a.splice(i, 1);
   }
}
console.log(a);//[1,3,5]

这里没有得到正确结果,因为删除数组项时改变了数组长度,而此时索引一直在递增,那么此时索引对应的值不再是原来值了。如下:

i = 0   =>   a=[1,2,3,4,5]

i = 1   =>   满足条件, a截取掉2,a=[1,3,4,5]

i = 2   =>   此时a[2]为4了,满足条件,a截取掉4,a=[1,3,5]

此时循环已经结束,因为此时a的length为3,索引已经为2了,无法再递增。

【解决方法1】:

由于循环索引一直在递增,而数组长度却减小了,导致索引对应的值错乱了且循环次数也减少了,那么就需要手动减小索引。

let a = [1, 2, 3, 4, 5];
for (var i = 0; i < a.length; i++) {
   if (a[i] >= 2 && a[i] < 5) {
      a.splice(i, 1);
      i--;//手动减索引,下一次循环i++ 那么就对应上了
   }
}
console.log(a);//[1,5]

【解决方法2】:

既然是由于索引一直在递增,而数组长度却可能减小,导致对应不上,那么如果索引一直递减,就算数组长度减少也能正确对应上。

let a = [1, 2, 3, 4, 5];
for (var i = a.length - 1; i > 0; i--) {
   if (a[i] >= 2 && a[i] < 5) {
      a.splice(i, 1);
   }
}
console.log(a);//[1,5]

当使用forEach:

let a = [1, 2, 3, 4, 5];
a.forEach((ele, ind) => {
    if (ele >= 2 && ele < 5) {
       a.splice(ind, 1);
    }
})
console.log(a)//[1, 3, 5]

这里也是没有得到正确结果,原因和上面一样。

【解决方法】:

这里不能像for循环那样控制索引,因为索引是由forEach内部自己控制的。如果硬要使用forEach的话,可以保存索引,然后使用filter过滤掉。由于这里会多一次filter循环,所以还不如不使用forEach,直接使用filter过滤。

当使用filter:

这种过滤需求使用filter是最简单的了。

let a = [1, 2, 3, 4, 5];
a = a.filter(ele => {
    return ele < 2 || ele >= 5;
})
console.log(a)//[1,5]

使用filter确实非常简单方便,但是很多时候我就需要使用splice方法来实现一些功能。这时候还是for循环方便了。

比如:let a = [1,2,3,4,5], b = a,c = a; 我需要改变a长度的同时也得改变b、c的长度。

如果使用filter不太方便:

let a = [1,2,3,4,5];
let b = a,c = a;

a = a.filter(ele => {
   return ele < 2 || ele >= 5;
});

b = a;
c = a;//使用filter不太方便,b、c必须得重新引用a,因为filter返回的是一个全新的数组。

使用for和splice就很方便了:

let a = [1, 2, 3, 4, 5];
let b = a, c = a;
for (var i = a.length - 1; i > 0; i--) {
   if (a[i] >= 2 && a[i] < 5) {
      a.splice(i, 1);
   }
}
console.log(a,b,c);//[1,5] [1,5] [1,5]

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值