Yet another list to range function

Originally posted on perlmonks.org on Jun 19, 2002

Yet Another List to Range function.

Takes an array and in list context returns an array. In scalar it returns a string. Ranges are separated by \s-\s so that you can easily split them without worrying about confusing them with negative numbers.

Handles numbers that begin with 0 as well. If not ints, makes a weak effort to handle fractions intervals. If your numbers are fractional and normalized, it should work ie ( 0.5 0.6 0.7)

(0.1 0.2 0.3) # Will work (0.1 00.20 0.3) # Won't work

#!/usr/bin/perl -w
use strict;

sub list2ranges {
    my @list    = sort { $a <=> $b } @_;
    my $current = $list[0];
    my @ranges  = ($current);
    for ( my $i = 1 ; $i <= @list ; $i++ ) {
        if (   $list[$i] && $list[$i] - $current == 1
            || $list[$i]
            && $list[$i] - $current < 1
            && substr( $list[$i], 0, -1 ) eq substr( $current, 0, -1 ) )
        {
            $current = $list[$i];
        }
        else {
            $ranges[-1] .= " - $current" if $ranges[-1] != $current;
            $list[$i] && push @ranges, $current = "$list[$i]";
        }
    }

    return wantarray ? @ranges : join( ", ", @ranges );
}

# Examples
my @test = (
    qw( 01 2 3), 5,
    ( 7 .. 9 ),
    ( 11 .. 12 ),
    ( 17 .. 19 ),
    20, 30, qw(30.1 30.2 30.33 30.34 30.35)
);
my @ranged = list2ranges(@test);

print join( ", ", @test ),   " \n";
print join( ", ", @ranged ), " \n";
print scalar( list2ranges(@test) ), "\n";
Scroll to top