Perhaps I have too much time on my hands. This sub allows you to change the separators and handles mixed letters and numbers, 0 and negative numbers. Can be called in scalar or list context.
#!/usr/bin/perl
use strict;
use warnings;
sub human {
# range separator defaults to '-'
my $range_separator = '-';
# last item separator defaults ''
my $last_item_separator = '';
# list separator for scalar context
my $list_separator = ', ';
if (ref $_[0] eq 'ARRAY') {
my $format = shift;
$range_separator = $$format[0] if $$format[0];
$last_item_separator = $$format[1] if $$format[1];
$list_separator = $$format[2] if $$format[2];
}
# get list;
my @array = @_;
# load first range
my @range = ($array[0], $array[0]);
shift @array;
# the human readable array
my @human;
# last item is a dummy, should be less than $array[-1]
foreach my $to (@array, $range[0]) {
# use autoincrement to get next item
my $next = $range[1];
$next++;
if ($next eq $to) {
# increase range
$range[1]++;
next;
}
# use autoincrement to get next item (for testing below)
$next = $range[0];
$next++;
# add current range to human readable array
push @human,
$range[1] eq $range[0] ? $range[0] :
$range[1] eq $next ? @range :
"$range[0]$range_separator$range
+[1]";
# load next range
@range = ($to, $to);
}
unless ($last_item_separator eq '') {
my $last_item = pop @human;
push @human, "$last_item_separator$last_item";
}
return wantarray ? @human : join $list_separator, @human;
}
my @array = (1, 2, 3, 5, 7, 8, 9, 11, 14);
print 'Read chapters: ', scalar human(@array), " before friday.\n";
print "Read these chapters by friday:\n", scalar human([' through ', '
+and ', "\n"], @array), "\n\n";
print 'Read pages: ', (join ', ', human(@array)), ".\n\n";
print join(', ', human(0, 2 .. 4, 6, 7, 9, 11 .. 14, 17 .. 19)), "\n";
print join(', ', human(1 .. 19)), "\n";
print scalar human(1 .. 19), "\n\n";
print "Mixed:\n";
@array = (0, 2 .. 4, 6, 7, 9, 'A' .. 'F', 11 .. 14, 'G', 17 .. 20);
print join(', ', human([' to '], @array)), "\n";
print scalar human(['-', '& '], @array), "\n\n";
print join(', ', human('aa' .. 'ba', -100 .. 4)), "\n";
print scalar human([' - ', undef, ' and '], 'aa' .. 'ba', '-100' .. 4)
+, "\n\n";
__END__
prints:
Read chapters: 1-3, 5, 7-9, 11, 14 before friday.
Read these chapters by friday:
1 through 3
5
7 through 9
11
and 14
Read pages: 1-3, 5, 7-9, 11, 14.
0, 2-4, 6, 7, 9, 11-14, 17-19
1-19
1-19
Mixed:
0, 2 to 4, 6, 7, 9, A to F, 11 to 14, G, 17 to 20
0, 2-4, 6, 7, 9, A-F, 11-14, G, & 17-20
aa-ba, -100-4
aa - ba and -100 - 4
HTH,
Charles K. Clarkson
Yep, way too much time
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.