It may be not worth it in this particular case, but Schwartzian transform technique can be used with multi-criteria sort too. Like this (codepad):
use warnings;
use strict;
my %myhash = (
cat_2 => 0, cat_04 => 1,
cat_03 => 0, dog_02 => 3,
cat_10 => 0, cat_01 => 3,
);
my @sorted =
map { [$_->[0], $myhash{$_->[0]}] }
sort { $a->[1] <=> $b->[1] or $a->[2] <=> $b->[2] }
map { m/([0-9]+)$/ && [$_, $myhash{$_}, $1] }
keys %myhash;
print $_->[0] . ' => ' . $_->[1] . "\n" for @sorted;
Obviously, the key to this technique is using more than one additional element in the cache.
Two things here: 1) @sorted actually becomes array of arrays (each element of this array is key-value pair); 2) sorting in this example is based on keys' digits suffix (with numeric, not string comparison), but it can be adjusted in any direction if needed.
For example, when keys match pattern XXX_DD_XXX (and it's DD that should be compared), change the second map clause with this:
map { m/_([0-9]+)_/ && [$_, $myhash{$_}, $1] }
2_is smaller than34both numerically and stringwise so that's a bad example. But I know what you meant. updated my answer - user2404501