# note passing your sub $a and $b foreach my $id (sort { mysort($direction,$a,$b) } keys %hash) { print "$id - $hash{$id}{$orderby}\n"; } # end-foreach sub mysort { my ($direction, $_a, $_b) = @_; my $result = $hash{$_a}{$orderby} <=> $hash{$_b}{$orderby} || $hash{$_a}{$orderby} cmp $hash{$_b}{$orderby}; # default to ascending, but if the dir is 'DESC', we # return the *opposite* answer return ($direction eq 'DESC') ? -($result) : $result; } #### # we pass the sub the actual values to compare foreach my $id ( sort { mysort($direction,$hash{$a}{$orderby},$hash{$b}{$orderby}) } keys %hash ) { print "$id - $hash{$id}{$orderby}\n"; } # end-foreach sub mysort { my ($direction, $_a, $_b) = @_; # generalized, simplified comparison my $result = $_a <=> $_b || $_a cmp $_b; # default to ascending, but if the dir is 'DESC', we # return the *opposite* answer return ($direction eq 'DESC') ? -($result) : $result; }