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";