sub compactRanges { # # @pieces contains the list of numbers # %parts will contain a compact form, such that $start..$end # is represented as $parts{$start} = $end # $seperator contains the character(s) placed between the # values # %wrap_negatives contains a flag indicated if negative # values should be wrapped in some way, and the leading # and trailing values if so # my (@pieces) = @_; my $seperator = '..'; my %wrap_negatives = ( 'flag' => 1, 'leading' => '[', 'trailing' => ']' ); my (%parts); @pieces = sort { $a <=> $b } @pieces; { my ($i); my ($recent); $recent = $parts{$i} = $i = shift (@pieces); while (@pieces) { $i = shift (@pieces); $recent = $i if ( $i - 1 > $parts{$recent} ); $parts{$recent} = $i; } } foreach my $k ( sort { $a <=> $b } keys(%parts) ) { my $str = ( ( $wrap_negatives{'flag'} ) and ( $k < 0 ) ? $wrap_negatives{'leading'} : '' ) . $k . ( ( $wrap_negatives{'flag'} ) and ( $k < 0 ) ? $wrap_negatives{'trailing'} : '' ); $str .= $seperator . ( ( $wrap_negatives{'flag'} ) and ( $parts{$k} < 0 ) ? $wrap_negatives{'leading'} : '' ) . $parts{$k} . ( ( $wrap_negatives{'flag'} ) and ( $parts{$k} < 0 ) ? $wrap_negatives{'trailing'} : '' ) if ( $parts{$k} != $k ); push ( @pieces, $str ); } return (@pieces); }