Can anybody tell me what I am doing wrong here? I have tried just about every possible combination of array / hash type and sort query I can think of and cannot seem to get this to work.
I am trying to sort the hash ref below by value1 :
my $test = {
'1' => { 'value1' => '0.001000', 'value2' => 'red'},
'2' => { 'value1' => '0.005000', 'value2' => 'blue'},
'3' => { 'value1' => '0.002000', 'value2' => 'green'},
'7' => { 'value1' => '0.002243', 'value2' => 'violet'},
'9' => { 'value1' => '0.001005', 'value2' => 'yellow'},
'20' => { 'value1' => '0.0010200', 'value2' => 'purple'}
};
Using this sort loop:
foreach (sort { $test{$a}->{'value1'} <=> $test{$b}->{'value1'} } keys \%{$test} ){
print "key: $_ value: $test->{$_}->{'value1'}\n"
}
I get:
key: 1 value: 0.001000
key: 3 value: 0.002000
key: 7 value: 0.002243
key: 9 value: 0.001005
key: 2 value: 0.005000
key: 20 value: 0.0010200
I have tried with integers and the same thing seems to happen.
I don't actually need to loop through the hash either I just want it ordered for later use. Its easy to do with an array of hashes, but not so with a hash of hashes..?
Don't call keys on a reference. Call it on the actual hash.
Also, this $test{$a}->, should be $test->{$a}, because $test is a hash reference.
foreach (sort { $test->{$a}{'value1'} <=> $test->{$b}{'value1'} } keys %{$test} ){
print "key: $_ value: $test->{$_}->{'value1'}\n"
}
If you had use strict; and use warnings; turned on, you would've gotten the following error to alert you to an issue:
Global symbol "%test" requires explicit package name
Just wanted to provide a source for the other answers, and a working code example. Like they said, you are calling keys with a hash reference for the argument. According to the documentation:
Starting with Perl 5.14, keys can take a scalar EXPR, which must contain a reference to an unblessed hash or array. The argument will be dereferenced automatically. This aspect of keys is considered highly experimental. The exact behaviour may change in a future version of Perl.
for (keys $hashref) { ... }
for (keys $obj->get_arrayref) { ... }
However this does work for me:
#!/usr/bin/perl
use strict;
use warnings;
my $test = {
'1' => { 'value1' => '0.001000', 'value2' => 'red'},
'2' => { 'value1' => '0.005000', 'value2' => 'blue'},
'3' => { 'value1' => '0.002000', 'value2' => 'green'},
'7' => { 'value1' => '0.002243', 'value2' => 'violet'},
'9' => { 'value1' => '0.001005', 'value2' => 'yellow'},
'20' => { 'value1' => '0.0010200', 'value2' => 'purple'}
};
foreach (sort { $test->{$a}->{'value1'} <=> $test->{$b}->{'value1'} } keys \%{$test} ) {
print "key: $_ value: $test->{$_}->{'value1'}\n"
}
Example:
matt@mattpc:~/Documents/test/10$ perl test.pl
key: 1 value: 0.001000
key: 9 value: 0.001005
key: 20 value: 0.0010200
key: 3 value: 0.002000
key: 7 value: 0.002243
key: 2 value: 0.005000
matt@mattpc:~/Documents/test/10$ perl --version
This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi
(with 88 registered patches, see perl -V for more detail)
This is with using a hash reference as the input to keys which I would not recommend.
I'd recommend following the advice of the other questions and adding use strict and use warnings and changing the hash reference to a hash, %{test}.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With