If I read your code correctly, only the inner loop on $ba is sorting on values. Hash keys are not returned in a specific order, so your $foo keys may be all over the place. But your expected output really looks to be sorting on key $foo, then on $ba, so I'm not sure "sorting on values" is you are asking. If it is, I would expect the following code snippet to generate your expected output:
use strict;
use warnings;
my %hoh_test = (
foo1 => { bar => -0.12697, baz => -0.000398154, },
foo2 => { bar => -4.0183e-05, baz => 0, },
foo3 => { bar => 9.966003977e-06, baz => 0.0001939, },
);
# Sort on $foo decending
foreach my $foo ( sort { $b cmp $a } keys %hoh_test ) {
# Sort on values decending
foreach my $ba (
sort { $hoh_test{$foo}{$b} <=> $hoh_test{$foo}{$a} }
keys %{$hoh_test{$foo}}
) {
printf "foo: %s, ba: %s, value: %s\n",
$foo,
$ba,
$hoh_test{$foo}{$ba};
}
}
The output matches your expected output:
$ perl 111142758a.pl
foo: foo3, ba: baz, value: 0.0001939
foo: foo3, ba: bar, value: 9.966003977e-06
foo: foo2, ba: baz, value: 0
foo: foo2, ba: bar, value: -4.0183e-05
foo: foo1, ba: baz, value: -0.000398154
foo: foo1, ba: bar, value: -0.12697
If instead you are sorting on $foo decending then on $ba decending, the code would instead be:
use strict;
use warnings;
my %hoh_test = (
foo1 => { bar => -0.12697, baz => -0.000398154, },
foo2 => { bar => -4.0183e-05, baz => 0, },
foo3 => { bar => 9.966003977e-06, baz => 0.0001939, },
);
# Sort on $foo decending
foreach my $foo ( sort { $b cmp $a } keys %hoh_test ) {
# Sort on $ba decending
foreach my $ba ( sort { $b cmp $a } keys %{$hoh_test{$foo}} ) {
printf "foo: %s, ba: %s, value: %s\n",
$foo,
$ba,
$hoh_test{$foo}{$ba};
}
}
This output also matches your expected output:
$ perl 111142758b.pl
foo: foo3, ba: baz, value: 0.0001939
foo: foo3, ba: bar, value: 9.966003977e-06
foo: foo2, ba: baz, value: 0
foo: foo2, ba: bar, value: -4.0183e-05
foo: foo1, ba: baz, value: -0.000398154
foo: foo1, ba: bar, value: -0.12697
If you really want your hash output sorted by values, there may be other ways but the simplest that comes to my mind is to push the order into a temporary structure you can actually sort:
use strict;
use warnings;
use utf8;
my %hoh_test = (
foo1 => { bar => -0.12697, baz => -0.000398154, },
foo2 => { bar => -4.0183e-05, baz => 0, },
foo3 => { bar => 9.966003977e-06, baz => 0.0001939, },
);
# Sort on values by pushing into an intermediary structure
my @ordering;
foreach my $foo ( keys %hoh_test ) {
foreach my $ba ( keys %{ $hoh_test{$foo} } ) {
push @ordering, { foo => $foo, ba => $ba, v => $hoh_test{$foo}
+{$ba}, };
}
}
# Sort intermediary structure on value (v) from above.
foreach my $i ( sort { $ordering[$b]{v} <=> $ordering[$a]{v} } 0 .. $#
+ordering ) {
printf "foo: %s, ba: %s, value: %s\n",
$ordering[$i]{foo},
$ordering[$i]{ba},
$ordering[$i]{v};
}
This also creates your expected output:
$ perl 111142758c.pl
foo: foo3, ba: baz, value: 0.0001939
foo: foo3, ba: bar, value: 9.966003977e-06
foo: foo2, ba: baz, value: 0
foo: foo2, ba: bar, value: -4.0183e-05
foo: foo1, ba: baz, value: -0.000398154
foo: foo1, ba: bar, value: -0.12697
Hope that helps.
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.