在Raku中是否有优雅方法判断两个Range是否重叠并计算重叠区间?
在Raku中判断Range重叠及获取重叠区间的方法
判断两个Range是否重叠
要判断两个Range是否存在重叠,最直接且高效的方式是利用它们的边界进行判断——无需生成集合(避免超大Range的性能问题)。核心逻辑是:只要其中一个Range的最小值不大于另一个的最大值,且反之亦然,就说明存在重叠。
可以封装成简洁的函数:
sub ranges-overlap(Range $a, Range $b) { not ($a.max < $b.min or $b.max < $a.min) } my $r = 1..10; my $r1 = 2..5; my $r2 = 7..15; say ranges-overlap($r, $r1); # True say ranges-overlap($r, $r2); # True say ranges-overlap($r1, $r2); # False
如果只是单次判断,甚至可以直接写 inline 表达式,无需封装函数:
say not ($r.max < $r2.min or $r2.max < $r.min); # True
获取重叠区间
Raku内置的∩运算符会将Range转换为Set进行交集运算,这不仅会丢失Range类型,还会在处理超大Range时导致严重的性能问题(因为要生成完整集合)。因此自定义一个针对Range的交集运算符是更优雅且高效的方案,你的实现已经很完善,这里可以做一点小优化,兼容非整数Range的场景:
sub infix:<∩>(Range $r1, Range $r2) { my ($min1, $max1) = $r1.bounds; my ($min2, $max2) = $r2.bounds; return Nil if $max1 < $min2 || $max2 < $min1; return max($min1, $min2) .. min($max1, $max2); } my $r = 1..10; my $r1 = 2..5; my $r2 = 7..15; say $r ∩ $r1; # 2..5 say $r ∩ $r2; # 7..10 say $r1 ∩ $r2; # Nil
如果仅需判断重叠状态,用边界判断法就足够;如果需要同时获取重叠区间,自定义运算符的方式既直观又高效,完全契合Raku的语法风格。
内容的提问来源于stack exchange,提问作者mscha
相关产品推荐
相关产品推荐

