When you sort strings alphabetically, you end up with
- Project 1 Report
- Project 10 Report
- Project 2 Report
- Project 3 Report
We’ve all seen this, right? Here’s an example in PERL:
my @examples = (
"Project 1 Report",
"Project 2 Report",
"Project 3 Report",
"Project 10 Report",
"Project 2342 Report",
"Alpha 2.9",
"Alpha 10.1" );
my @sorted = sort @examples;
print join( "\n",@sorted )."\n";
This’ll give you:
Alpha 10.1
Alpha 2.9
Project 1 Report
Project 10 Report
Project 2 Report
Project 2342 Report
Project 3 Report
What we really want is an alphabetic sort that treats numbers magically.
Here’s a quick fix to make it do the thing you meant, by zero-padding any numbers before comparing the strings:
my @sorted = sort sensible_sort @examples;
print join( "\n",@sorted )."\n";
sub sensible_sort {
my $a1=$a;
my $b1=$b; # clone these so we don't modify originals
$a1 =~ s/(\d+)/sprintf("%020d",$1)/ge;
$b1 =~ s/(\d+)/sprintf("%020d",$1)/ge;
return $a1 cmp $b1;
}
This modifies the strings used in the sort comparisons by finding every string of one or more digits 0-9 and replacing it with a 20 digit version, padded with zeroes. (20 digits is a number picked from my arse, 6 would probably do). This technique is easy enough to do in C or php or whatnot. There may well be a library out there which already does it, but it’s a neat self-contained little technique, which makes our lists from our learning objects repository far saner. Lecture 10 was listed second!
