Try this on for size:
#!/usr/bin/perl -w
use Carp;
my %people = (
Bob => { age => 60, town => 'Harrisburg' },
Joe => { age => 55, town => 'Calgary' },
Sue => { age => 40, town => 'Houston' },
Jim => { age => 42, town => 'Dresden' },
Ann => { age => 47, town => 'Los Angeles' },
);
my %data_types = (
age => 'numeric',
town => 'text',
# etc...
);
sub sort_people_by {
my ($people,$sortby,$dir) = @_;
my $dtype = $data_types{$sortby};
if(!$dtype) {
croak "No data type defined for $sortby";
}
elsif($dtype eq 'numeric') {
if($dir eq 'ASC') {
return sort { $people->{$a}->{$sortby}
<=> $people->{$b}->{$sortby} }
keys %$people;
}
else {
return sort { $people->{$b}->{$sortby}
<=> $people->{$a}->{$sortby} }
keys %$people;
}
}
elsif($dtype eq 'text') {
if($dir eq 'ASC') {
return sort { $people->{$a}->{$sortby}
cmp $people->{$b}->{$sortby} }
keys %$people;
}
else {
return sort { $people->{$b}->{$sortby}
cmp $people->{$a}->{$sortby} }
keys %$people;
}
}
else {
croak "Data type $dtype unknown";
}
}
sub print_people_sorted_by {
my ($people,$sortby,$dir) = @_;
foreach my $person
(sort_people_by($people,$sortby,$dir)) {
print "$person - $people{$person}{$sortby}\n";
}
}
print_people_sorted_by(\%people,'age','ASC');
print_people_sorted_by(\%people,'town','DESC');
Updated style to be closer to PBP, since I need the practice anyways - old habits die hard :)