That uses a technique called a Schwartzian Transform, but you don't need to use it here. Aside from that, I'm not 100% sure that the comparison is going to work in all cases. It may very well. Below is another way.
Basically compare using "cmp" if both things contain a non-digit, use "<=>" if both things are pure digits, if there is a mixture (one thing is pure digits, one thing is not) then the pure digit thing appears before the other in sort order. The sort subroutine needs to return, -1(a<b),0(a=b),1(a>b)and you can have any code to do that that you want. Perhaps you would want say some function that sorted the days of the week, in Europe weeks start on Monday, but in the US weeks start on Sunday. You could do that by making a subroutine that returns the appropriate -1,0,1 values. Cool.
@sorted = sort by_num_then_letter @unsorted;
sub by_num_then_letter
{
my $a_region = lc ($a->region_name);
my $b_region = lc ($b->region_name);
my $a_non_digit = ($a_region =~ /\D/);
my $b_non_digit = ($b_region =~ /\D/);
if ($a_non_digit and $b_non_digit)
{
$a_region cmp $b_region
}
elsif (!$a_non_digit and !$b_non_digit)
{
$a_region <=> $b_region
}
elsif ($a_non_digit) #digit only thing is always less than
{
1; # b > a (reverse 1 and -1 if I got this wrong)
}
else
{
-1; # b<a
}
}
|