in reply to Sorting a hash of a hash using anonymous subs

while ( my ($test,$val) = each %{$sorter->()} ) calls &$sorter every time through the loop. That meeans that &$sorter creates a new hash and sorts it every time through the loop. It also means you keep calling each on a new hash every time. None of that is good. Also, you want the keys, but you discard them by using values.

The trick is to sort the keys (by value, if so desired) into an array, and loop over that array.

my @ordered_keys; if ($sort eq 't') { # Calculate the order in which we want to process %tests. # (Sort keys by ascending numerical Total.) @ordered_keys = sort { $tests{$a}{Total} <=> $tests{$b}{Total} } keys %tests; } elsif ($sort eq 'v') { # Calculate the order in which we want to process %tests. # (Sort keys by ascending numerical Value.) @ordered_keys = sort { $tests{$a}{Value} <=> $tests{$b}{Value} } keys %tests; } foreach my $key (@ordered_keys) { my $val = $tests{$key}; print "$key\n"; print " Total: $val->{Total}\n"; print " Value: $val->{Value}\n\n"; }

By the way, you were sorting alphabetically. Now, it's sorting numerically.

By the way, when dumping a hash or an array, pass a reference to the variable to Dumper (e.g. print Dumper \%tests;) for better results.

Update: The only purpose of using a sub would be to delay the calculation of @ordered_keys. If that's what you wish to do, what follows is a transformation of the above which postpones the calculation of @ordered_keys by use of a sub:

my $sorter; if ($sort eq 't') { # Sort keys by ascending numerical Total. $sorter = sub { my ($tests) = @_; return sort { $tests->{$a}{Total} <=> $tests->{$b}{Total} } keys %$tests; }; } elsif ($sort eq 'v') { # Sort keys by ascending numerical Value. $sorter = sub { my ($tests) = @_; return sort { $tests->{$a}{Value} <=> $tests->{$b}{Value} } keys %$tests; }; } foreach my $key ($sorter->(\%tests)) { my $val = $tests{$key}; print "$key\n"; print " Total: $val->{Total}\n"; print " Value: $val->{Value}\n\n"; }

foreach will build the list over which it iterates only once, so it doesn't suffer the same problem as your while solution.