in reply to Sorting a hash of a hash using anonymous subs
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.
|
|---|