sub my_sort_index {
my ($c, $d) = @_;
# We want any item starting with "index." to sort to the top of
# the list. The rest of the ordering is handled by the caller.
# So there are four cases we must handle:
#
# Matches?
# $c $d return
# No No 0
# Yes No -1
# No Yes +1
# Yes Yes 0 (-1 + +1 == 0)
#
# In the fourth case, when both strings have the "index." prefix,
# we want them to sort via the normal method so that "index.1" will
# always sort before "index.2".
my $return_value = 0;
--$return_value if $c =~ /^index\./;
++$return_value if $d =~ /^index\./;
return $return_value;
}
####
my @sorted = sort { my_index_sort($a,$b) || $b cmp $a } @list;
####
sub convert_name_to_L_F_M_Extras {
# Lots of ugly code to split the name into bits, determine which bit goes where, and
# return an array of [ LastName, FirstName, MiddleName, Extras ], like so:
# "Dr. John Smith" => [ Smith, John, undef, Dr. ]
# "Eucalyptus A. Tree, Esquire" => [ Tree, Eucalyptus, A., Esquire ]
return [ $last, $first, $middle, $rest ];
}
my @list = ( "Dr. John Smith", "Eucalyptus A. Tree, Esquire", "Roboticus", "Lady Aleena, Baker of cookies" );
my @transformed_list = map { [ convert_name_to_L_F_M_Extras($_), $_ ], } @list;
# Now looks like:
# @transformed_list = (
# [ [ "Smith", "John", undef, "Dr" ], "Dr. John Smith" ],
# [ [ "Tree", "Eucalyptus", "A.", "Esquire" ], "Eucalyptus A. Tree, Esquire" ],
# ...
# );
sub sort_by_name {
# $a and $b contain an arrayref, the first entry has an arrayref with last, first, etc.
# Sort by last name:
$a->[0][0] cmp $b->[0][0]
# If they have the same last name, sort by first name:
|| $a->[0][1] cmp $b->[0][1]
... etc ...
}
my @sorted = sort {sort_by_name($a,$b)} @transformed_list;
# Now throw away the transformed names and keep only the list of sorted names.
@sorted = map { $_->[1] } @sorted;