Perl使用splice删除数组连续重复值未达预期原因排查
问题原因
- 核心问题是你在遍历数组的同时修改了数组的长度,且索引递增逻辑错误导致元素被跳过:
初始数组为['A','B','B','C'],第一次匹配到索引为1的B时,调用splice删除该位置元素后,原数组变为['A','B','C'],原本第二个B的位置从索引2前移到了索引1。此时你的代码直接执行$j++将索引变为2,下一次循环直接判断索引2的C,就漏掉了移位到索引1的B,最终只删除了一个B。 - 额外注意:不要用
foreach遍历正在被修改的原数组,遍历过程中数组长度变化会导致不可预期的遍历行为。
修正方案
方案1:删除数组中所有值为B的元素
改用while遍历索引,仅在未命中删除逻辑时才递增索引,避免漏判:
use Data::Dumper; my $tmp_h = {}; @{$tmp_h->{'a'}} = qw/A B B C/; print Dumper ($tmp_h); my $j = 0; # 动态获取数组最大索引,适配长度变化 while ($j <= $#{$tmp_h->{'a'}}) { if ($tmp_h->{'a'}[$j] eq 'B') { splice(@{$tmp_h->{'a'}}, $j, 1); } else { $j++; } } print Dumper $tmp_h;
方案2:通用实现:删除数组中所有相邻重复元素
如果你的需求是删除所有相邻的相同值(不限定是B),更推荐用生成新数组的方式实现,性能更稳定,不会出现索引错位问题:
use Data::Dumper; my $tmp_h = {}; @{$tmp_h->{'a'}} = qw/A B B C C C D/; print Dumper ($tmp_h); my @result; my $prev_val; foreach my $cur (@{$tmp_h->{'a'}}) { # 仅当前值和上一个保留值不同时才存入结果 if (!defined $prev_val || $cur ne $prev_val) { push @result, $cur; $prev_val = $cur; } } @{$tmp_h->{'a'}} = @result; print Dumper $tmp_h;
内容的提问来源于stack exchange,提问作者user1550596
相关产品推荐
相关产品推荐

