top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

Perl: series of numbers to range notation

+2 votes
613 views

I have this series of numbers:

349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,
373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,
425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,
449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,
473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496

there are two ranges in there: 349-396, 425-496. Any hints as to how to write a perl code to represent the series of numbers as a range?

posted Jan 7, 2014 by Sumit Pokharna

Share this question
Facebook Share Button Twitter Share Button LinkedIn Share Button
(349..396,425..496);

2 Answers

+1 vote

simply looping through the range in numerical order, checking if the number you're looking at is one higher than the last, and either adding it to the "current" range if so, or starting a new range if not, should be pretty easy - e.g. assuming @nums contains that sorted list of numbers, then:

my @ranges;
my @current_range;
my $lastnum;

for my $num (@nums) {
 # See if we're starting a new range - if so, add the last range 
 # to the set of ranges we've found:
 if (@current_range &
 @current_range = ($num);
 # Otherwise, just add this number to the current range
 } else {
 push @current_range, $num;
 }

 $lastnum = $num;
}

# Finally, when we've run out of numbers, we might have a remaining
range left # to add, so handle that:
if (@current_range) {
 push @ranges, (@current_range > 1)
 ? $current_range[0] . '-' . $current_range[-1]
 : @current_range;
}

There are likely shorter and more elegant ways than the above, though.

answer Jan 7, 2014 by Sanketi Garg
+1 vote
perl -wE'
 my $csv = q{
 1, 2, 4, 5, 6, 8, 9, 10,
 349,350,351,352,353,354,355,356,357,358,
 359,360,361,362,363,364,365,366,367,368,
 369,370,371,372,373,374,375,376,377,378,
 379,380,381,382,383,384,385,386,387,388,
 389,390,391,392,393,394,395,396,425,426,
 427,428,429,430,431,432,433,434,435,436,
 437,438,439,440,441,442,443,444,445,446,
 447,448,449,450,451,452,453,454,455,456,
 457,458,459,460,461,462,463,464,465,466,
 467,468,469,470,471,472,473,474,475,476,
 477,478,479,480,481,482,483,484,485,486,
 487,488,489,490,491,492,493,494,495,496
 };

 (my $ssr = $csv) =~ s/[^d,]//ga;
 1 while $ssr =~ s/b(d+),(d+)b/($1==$2-1)?"$1-$2":"$1;$2"/e;
 $ssr =~ s/-d+(?=-)//g;

 say $ssr;
'
1-2;4-6;8-10;349-396;425-496
(made for unsigned numbers)
answer Jan 8, 2014 by Naveena Garg
Similar Questions
+2 votes

I have this simple script to automatically print HTML selection option.

#!/usr/bin/env perl
use strict;
for (reverse(1943 .. 1991)){
  print "$_n";}

I need to print all the years between 18 and 73 without hard coding the range in the for loop as in the above. I am considering the use of localtime to compute the current year as below $yr=(localtime), but I cant think of an easy way to achieved what I want to do.

+1 vote

I'm looking for introductory to advanced examples of RESTful programming in Perl preferably with some good explanations and best practices.

...