2014-11-21 67 views
0

解釋我的疑問最簡單的方法是一個例子...所以這裏是:如何從perl中的時間間隔數組中獲得補數區間?

我有一個數組在perl與一組間隔,我需要獲得補充區間,換句話說,那套的形象。自:

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

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

把它轉換爲:

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

非常感謝您提前爲您考慮!

+0

你的'...'是什麼? – toolic 2014-11-21 15:28:30

+0

要說你沒有該地區的信息 – Mastodon 2014-11-21 15:36:41

回答

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-... 
+0

它適用於這個問題!非常感謝 – Mastodon 2014-11-21 15:45:35

+0

該程序的輸出與問題中所述的所需輸出不符。 – Borodin 2014-11-21 17:08:28

+0

@Borodin:謝謝,修正。 – choroba 2014-11-21 17:13:23

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 
+0

雖然似乎沒有涵蓋上下界嗎? – Sobrique 2014-11-21 15:24:58

+0

@Sobrique:OP應該明確指定上下界限,而不是'...' – toolic 2014-11-21 15:26:05

+1

它似乎對於我必須解決的某些特定情況正常工作,謝謝! – Mastodon 2014-11-21 15:46:12

0

你可能更喜歡這種解決方案,其工作原理類似於來自的答案。

我已經使用Data::Dump顯示了結果@pairs陣列,它顯示了數組的內容以防需要進一步處理,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-... 
0

要學究,沒有提供的解決方案的工作,如果給定一組包含-Inf或+天道酬勤,如:('...-22', '45-84', '128-167', '210-...')

如果間隔排序並且不重疊,並且數據總是符合給定的語法,這裏也是一種解決方案,它也適用於上述情況(其與@Borodin提供的非常類似):

use strict; 
use warnings; 

my @data = ('...-22', '45-84', '128-167', '210-...'); 

use constant { 
    SEP  => '-' , 
    NEG_INF => '...', 
    POS_INF => '...' 
}; 

my ($first, $prev_upper) = split SEP, shift @data; 
my @res = $first eq NEG_INF 
    ?() : join SEP, NEG_INF, $first - 1; 

for (@data) { 
    my ($lower, $upper) = split SEP; 
    push @res, join SEP, $prev_upper + 1, $lower - 1; 
    $prev_upper = $upper 
} 
push @res, join SEP, $prev_upper + 1, POS_INF 
    unless $prev_upper eq POS_INF; 

print join ' ', @res; # 23-44 85-127 168-209 
相關問題