harishnuti has asked for the wisdom of the Perl Monks concerning the following question:


Hello Monks
i have one subroutine which will take input the range of numbers and gives the expansion of it.
to be clear , if i input 2-8,10-13,18 it will give 2,3,4,5,6,7,8,10,11,12,13,18 which iam going to use it in my array extraction..
subroutine is as below(just framed as one example)...
#!/usr/bin/perl print "To get the range of numbers \n"; print "Enter the range to see expansion \n"; chomp($range=<STDIN>); print "The range from subroutine is :",join("==>",&get_numbers_from_ra +nges($range)),"\n"; sub get_numbers_from_ranges { my $spec = shift; my %numbers; foreach my $x ( split ',', $spec ) { $x =~ s/\s*//g; if ( $x =~ /(\d+)-(\d+)/ ) { $numbers{$_} = undef for $1 .. $2; } else { $numbers{$x} = undef; } } # subtracting every element by one because these are used in array +s i.e. 1st element in array index is 0 #return map { $_ - 1 } sort { $a <=> $b } keys %numbers; return map { $_ - 1 } keys %numbers; }

my problem is , i dont want the result to be sorted , i want the result unsorted .
for instance, if i give input as 6-9,1-3,11 i need output as 6,7,8,9,1,2,3,11 , but iam not able to achieve this, by using sort iam getting 1,2,3,6,7,8,9,11 which is not iam looking for.
if i remove sort statement as see above in code, iam getting wrong output
pls help me to fix the above code where i get the expansion of numbers in the order i inputted..

Replies are listed 'Best First'.
Re: Extracting Ranges from Sequences using hashes
by GrandFather (Saint) on Sep 25, 2008 at 04:11 UTC

    Get rid of the hash, at least for storing the numbers. I presume you need it to ensure numbers are unique if ranges overlap. I'd do something like:

    use strict; use warnings; my @nums = get_numbers_from_ranges ('2,10-13,2-5'); print "@nums"; sub get_numbers_from_ranges { my @ranges = split ',', shift; my @numbers; my %seen; for my $range (@ranges) { my ($start, $end) = sort {$a <=> $b} split '-', $range; $end ||= $start; ! $seen{$_}++ and push @numbers, $_ for $start .. $end; } return @numbers; }

    Prints:

    2 10 11 12 13 3 4 5

    Perl reduces RSI - it saves typing

      Thanks a lot , i got it .. Thanks everyone for suggestions, i have taken all suggestions which improved my skills a bit
Re: Extracting Ranges from Sequences using hashes
by jwkrahn (Abbot) on Sep 25, 2008 at 04:34 UTC
    $ perl -le' my $range = "6-9,1-3,11"; $range =~ s/-/../g; my @numbers = eval $range; print "@numbers"; ' 6 7 8 9 1 2 3 11
Re: Extracting Ranges from Sequences using hashes
by andreas1234567 (Vicar) on Sep 25, 2008 at 11:30 UTC
    Or you could let Number::Range do it for you:
    use strict; use warnings; use Test::More; use Number::Range; sub get_numbers_from_ranges { my @ranges = split ',', shift; my @numbers = (); for my $range (@ranges) { my ($start, $end) = split '-', $range; push @numbers, ($end) ? Number::Range->new("$start..$end")->range() : $start; } return \@numbers; } plan tests => 2; is_deeply( get_numbers_from_ranges("2-8,10-13,18"), [ 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 18 ] ); is_deeply( get_numbers_from_ranges("6-9,1-3,11"), [ 6, 7, 8, 9, 1, 2, 3, 11 ]); __END__
    $ prove 713553.pl 713553....ok All tests successful. Files=1, Tests=2, 0 wallclock secs ( 0.04 cusr + 0.01 csys = 0.05 C +PU)
    --
    No matter how great and destructive your problems may seem now, remember, you've probably only seen the tip of them. [1]
Re: Extracting Ranges from Sequences using hashes
by johngg (Canon) on Sep 25, 2008 at 10:00 UTC
    Another solution using a split, a regex capture inside a map, and a grep.

    use strict; use warnings; my $rangeStr = q{2,10-13,2-5, 7, 32-28,12 , 18 - 23, 31-35}; my %seen = (); my @expandedRange = grep { not $seen{ $_ } ++ } map { m{(\d+)\s*-\s*(\d+)} ? $2 > $1 ? $1 .. $2 : reverse $2 .. $1 : $_; } split m{\s*,\s*}, $rangeStr; print qq{@expandedRange\n};

    The output.

    2 10 11 12 13 3 4 5 7 32 31 30 29 28 18 19 20 21 22 23 33 34 35

    I hope this is of interest.

    Cheers,

    JohnGG

Re: Extracting Ranges from Sequences using hashes
by parv (Parson) on Sep 25, 2008 at 04:22 UTC