[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [FWP] Formatting integer sets with ranges



Ofer Inbar wrote:
> 
> Rick <rklement@pacbell.net> wrote:
> >
> > Peter Scott wrote:
> > >
> > > $_ = '1,2,3,5,6,7,8,9,10,11,12,13,14,16,17,19,20,21';
> > >
> > > s/(\d+),\d+,(\d+)/$2==$1+2?"$1-$2":$&/eg;
> > > s/-(\d+),(\d+)/$2==$1+1?"-$2":$&/eg;
> > > 1 while s/-\d+(-\d)/$1/g;
> > >
> > > print "$_\n";
> > >
> > > 1-3,5-14,16,17,19-21
> > >
> > > Has the property of not hyphenating itmes differing only by 1, a pet peeve
> > > of mine.
> >
> > 1,2,3,4,5,8,9,10 => 1-4,5,8,9,10   ????
> >
> > That three-at-a-time probably needs a "1 while ..."
> 
> I think all you need to do is run the second substitution twice.  The
> problem is that putting a /g on that substitution isn't good enough
> because wherever it does succeed, the next number it needs to start
> matching at on the next iteration, to be correct, is the thing it just
> substituted in, and /g (for obvious reasons) will skip that and start
> one element later in the list.  But at most it will skip one step of
> "dashifying" at a time, and correctly "dashify" the next pair.  So if
> you run it a second time, you catch everything it missed the first run.
> 
> Putting a "1 while" on either of the /eg substitutions won't work,
> because part of the logic of whether or not to alter the string is in
> the substitution part.  The match part of these s///eg's will *always*
> match something in the list, as long as the list has more than one
> number in it, even if there's nothing left to alter.  So a while will
> never terminate.
> 
> sub hyphenatedlist
> { local($_) = join(',', sort @_);
> 
>   s/(\d+),\d+,(\d+)/$2==$1+2?"$1-$2":$&/eg;
>   s/-(\d+),(\d+)/$2==$1+1?"-$2":$&/eg;
>   s/-(\d+),(\d+)/$2==$1+1?"-$2":$&/eg;
>   1 while s/-\d+(-\d)/$1/g;
> 
>   return $_;
> }
> 

Yeah...

Or...

The overlaps can be avoided with zero width look ahead, then
clean up single ranges afterward if desired:

  $_ = join ',', @issues;

  s/(\d+),(?=(\d+))/$1+1==$2?"$1-":"$1,"/eg;
  s/-[^,]+-/-/g;                              # no need for 1 while
  s/(\d+)-(\d+)/$1+1==$2?"$1,$2":"$1-$2"/eg;  # fix single range

  print "$_\n";



-- 
Rick

==== Want to unsubscribe from Fun With Perl?  Well, if you insist...
==== Send email to <fwp-request@technofile.org> with message _body_
====   unsubscribe