Don't know if this solution is really preferable to any of the others, but its got a s/// in there! Uses state feature (available with 5.10+), but could easily avoid it. Note that it does not bother to range-ize a degenerate range: '1,2' does not become '1-2'.
>perl -wMstrict -le "use feature 'state'; ;; my $s = '2,3,5,6,7,9,11,12,13,14,16,17,19'; print qq{'$s' \n}; ;; my $sep = qr{ \s* , \s* }xms; my $n = qr{ \d+ }xms; ;; sub order { state $p = 0; my $t = $p; $p = $_[0]; return $_[0] - $t == 1; } ;; use re 'eval'; $s =~ s{ (?<! \d) ($n) (?{ order($^N) }) (?= $sep ($n) (?(?{ ! order($^N) }) (*F)) (?: $sep ($n) (?(?{ ! order($^N) }) (*F)))+ ) .+? \3 (?! \d) } {$1-$3}xmsg; ;; print qq{'$s' \n}; " '2,3,5,6,7,9,11,12,13,14,16,17,19' '2,3,5-7,9,11-14,16,17,19'
Update: Actually, the non-capturing look-ahead folderol is not needed. The following s/// seems to work just as well.
$s =~ s{ (?<! \d) ($n) (?{ order($^N) }) (?: $sep ($n) (?(?{ ! order($^N) }) (*F))){2,} } {$1-$2}xmsg;
Update: Even slightly simpler and no numbered capture group variables, but \K only available with 5.10+, like state.
sub order { state $p = 0; my $t = $p; $p = $^N; return $^N - $t == 1; } $s =~ s{ (?<! \d) ($n) \K (?{ order() }) (?: $sep ($n) (?(?{ ! order() }) (*F))){2,} } {-$^N}xmsg;
In reply to Re^2: Converting a list of numbers to use a range operator
by AnomalousMonk
in thread [Solved] Converting a list of numbers to use a range operator
by FloydATC
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |