Perl合并连续数字范围异常:Number::Range模块未输出预期结果
Perl合并连续数字范围异常:Number::Range模块未输出预期结果
嘿,我明白你遇到的问题了——想用Perl合并连续数字范围,结果用Number::Range模块跑出来的结果和预期完全不符对吧?我来帮你梳理下问题和解决办法。
首先先还原你的代码和实际输出:
你的测试代码
use Data::Dumper; use Number::Range; say STDERR Dumper(Number::Range->new("1000..5555,5559..9999,5556..5557,5558")->rangeList);
实际输出结果
$VAR1 = [ 5556, 5558 ]; $VAR2 = [ 5559, 9999 ]; $VAR3 = [ 1000, 5555 ];
你预期的结果
$VAR1 = [ 1000, 9999 ];
问题原因
其实Number::Range模块的new方法默认不会自动合并连续或重叠的数字区间,它只是将输入的范围字符串拆分为独立的条目,内部可能会做简单排序,但并没有实现区间合并的逻辑,所以才会输出分散的几个区间。
解决方案
这里提供两种可行的解决思路:
1. 手动实现区间合并逻辑
我们可以自己解析范围字符串,排序后遍历合并连续区间,代码示例如下:
use Data::Dumper; # 输入的范围字符串 my $range_str = "1000..5555,5559..9999,5556..5557,5558"; my @ranges; # 拆分并解析每个范围项(处理区间和单个数字) foreach my $item (split /,/, $range_str) { if ($item =~ /^(\d+)\.\.(\d+)$/) { push @ranges, [$1, $2]; } elsif ($item =~ /^(\d+)$/) { push @ranges, [$1, $1]; } } # 按区间起始数字排序 @ranges = sort { $a->[0] <=> $b->[0] } @ranges; # 合并连续/重叠的区间 my @merged; foreach my $range (@ranges) { if (!@merged) { push @merged, $range; next; } my $last = $merged[-1]; # 判断当前区间是否能和最后一个合并区间连续(包含重叠的情况) if ($range->[0] <= $last->[1] + 1) { # 更新合并区间的结束值为较大的那个 $last->[1] = $range->[1] if $range->[1] > $last->[1]; } else { push @merged, $range; } } # 输出合并后的结果 say STDERR Dumper(\@merged);
运行这段代码后,就能得到你预期的合并结果:[[1000, 9999]]
2. 使用更适合的专业模块
如果你不想自己写逻辑,可以用Set::IntSpan模块,它专门用于处理整数范围的合并、交集等操作,用法非常简洁:
use Data::Dumper; use Set::IntSpan; # 注意这里用横杠'-'分隔区间,和Number::Range的'..'略有不同 my $span = Set::IntSpan->new("1000-5555,5559-9999,5556-5557,5558"); # spans方法返回合并后的区间数组 say STDERR Dumper($span->spans);
这个模块会自动帮你合并所有连续的区间,直接输出你想要的结果。
备注:内容来源于stack exchange,提问作者h q
相关产品推荐
相关产品推荐

