LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   One last Perl Regular Expression Question (https://www.linuxquestions.org/questions/programming-9/one-last-perl-regular-expression-question-634529/)

gliesian 04-10-2008 08:32 PM

One last Perl Regular Expression Question
 
Let's say the following is the contents of an Perl array:

.1.
.2.
.3.
.5.
.6.
.7.
.8.
.11.
.12.
.14.


I need it to rework the array to look like this:

.1-3.
.5-8.
.11-12.
.14.

Well, there is actually a whole lot more to what I need to do... but I'm starting with this.

Any help with reducing this algorithm to Perl code would be appreciated.

matthewg42 04-10-2008 09:09 PM

Well, AFAIK, there's no regular expression method for this, although you might use regular expressions as part of a solution. I'd get an array with a list of the numbers (no dots), sort it in numerical order, and then count up the list... with a few well places ifs and a variable to store the last value you should be able to make something which creates these range strings.

gliesian 04-10-2008 09:21 PM

Thanks for the help...
 
Quote:

Originally Posted by matthewg42 (Post 3117481)
Well, AFAIK, there's no regular expression method for this, although you might use regular expressions as part of a solution. I'd get an array with a list of the numbers (no dots), sort it in numerical order, and then count up the list... with a few well places ifs and a variable to store the last value you should be able to make something which creates these range strings.

The regex part is the piece I left out, as these are the third octets in IP addresses.

I did write a sloc code counter in Tcl/Tk a few years back... I think I will adapt a similar approach to this task as what I had done before. I just need to get familar with Perl... quickly.

Thanks for your help!

osor 04-11-2008 05:21 PM

I don’t understand the question. How are you choosing the values you want? Are those “ranges” or literal strings? It is hard to tell since you don’t supply any code.

If you want ranges, you can use array slices in anonymous arrays. For example, if I have:
Code:

@a = ("1", "2", "3", "5", "6", "7", "8", "11", "12", "14");
I can have an array @b whose elements are references to the arrays containing the desired ranges like so:
Code:

@b = ([@a[0..2]], [@a[3..6]], [@a[7..8]], [@a[9]]);

angrybanana 04-11-2008 05:43 PM

There's probably a cleaner way to do this, but here's one solution
Code:

@a=qw/.1.  .3.  .5.  .6.  .7.  .8.  .11.  .12.  .14. /;
#filter out the '.' at the start and end
@clean = map {s/^\.//;s/\.$//;$_} @a;

#this makes it loop one extra time (so it does the last set correctly)
$#clean = $#clean+1;
#set initial values
$start = shift @clean;
$end = $start;
for $i (@clean){
  if ($i==$last+1){
    $end = $i;
  }
  else {
    if ($start==$end){
      $out = ".$start.";
    } else {
      $out = ".$start-$end.";
    }
    push @out, $out;
    $start = $i;
    $end = $i;
  }

  $last = $i;
}
print "$_\n" for @out;

output:
Code:

$ perl test.pl
.1.
.3.
.5-8.
.11-12.
.14.

I assume this is what you want? Not much of a regex question (aside from stripping the leading/trailing '.')

EDIT: I can do this a lot easier in python using groupby(), if perl has an equivalent function it'd make your life a lot easier.


All times are GMT -5. The time now is 11:24 AM.