Perl: the Markov chain saw PerlMonks

### Re^2: Converting a list of numbers to use a range operator

by AnomalousMonk (Canon)
 on Mar 24, 2013 at 00:28 UTC ( #1025100=note: print w/replies, xml ) Need Help??

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;

Create A New User
Node Status?
node history
Node Type: note [id://1025100]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (10)
As of 2017-06-26 12:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
How many monitors do you use while coding?

Results (579 votes). Check out past polls.