如何从perl中的一系列区间中获得补码区间?

时间:2014-11-21 15:14:20

标签: arrays perl intervals

解释我怀疑的最简单方法就是一个例子......所以这是:

我在perl中有一组带有一组间隔的数组,我需要获得互补的间隔,换句话说,就是那个集合的反映像。从:

  

@ ary1 = qw(23-44 85-127 168-209)

     

印刷间隔:23-44,85-127,168-209。

将其转换为:

  

...- 22,45-84,128-167,210 -...

非常感谢您的考虑!

4 个答案:

答案 0 :(得分:4)

如果间隔已经排序且不重叠:

#!/usr/bin/perl
use warnings;
use strict;

use List::MoreUtils qw{ natatime };

my @ary1 = qw(23-44 85-127 168-209);

my $diff = 1;
my $pair = natatime 2, '...', 
                       map({ map { $diff *= -1; $_ + $diff }
                                 split /-/
                           } @ary1),
                       '...';
my @compl;
while (my ($from, $to) = $pair->()) {
    push @compl, "$from-$to";
}

print "@compl\n";

<强>输出

...-22 45-84 128-167 210-...

答案 1 :(得分:3)

Set::IntSpan

use warnings;
use strict;
use Set::IntSpan;

my @ary1 = qw(23-44 85-127 168-209);
my $spec = join ',', @ary1;
my $set  = Set::IntSpan->new($spec);
my $list = $set->holes();
print "$list\n";

__END__

45-84,128-167

答案 2 :(得分:0)

您可能更喜欢此解决方案,其效果类似于@Choroba的答案。

我使用@pairs显示了结果Data::Dump数组,它显示了数组的内容(如果您需要进一步处理它),print,它会输出文本符合你在问题中的要求。

use strict;
use warnings;

my @input = qw/ 23-44 85-127 168-209 /;

my $begin;
my @pairs;

for (@input) {
  next unless /(\d+)-(\d+)/;
  push @pairs, [ $begin // '...', $1-1 ];
  $begin = $2+1;
}
push @pairs, [ $begin, '...' ];



use Data::Dump;
dd \@pairs;

print join(', ', map join('-', @$_), @pairs), "\n";

<强>输出

[["...", 22], [45, 84], [128, 167], [210, "..."]]
...-22, 45-84, 128-167, 210-...

答案 3 :(得分:0)

要迂腐,如果给定的集合包含-Inf或+ Inf,则所提供的解决方案都不起作用,例如:('...-22', '45-84', '128-167', '210-...')

如果区间被排序并且不重叠并且数据总是符合给定的语法,这里的解决方案也适用于上述情况(这与{{1提供的非常相似) }}):

@Borodin