Perl: Access a hashref sorted by value
I'm writing a script that'll read through my ftpd logs and generate a hash as follows:
$stats = \{
'user1' => {
'files' => 281,
'size' => '3724251021'
},
'user2' => {
'files' => 555,
'size' => '7385856997'
开发者_StackOverflow中文版 },
'user3' => {
'files' => 235,
'size' => '3716904486'
},
'user4' => {
'files' => 578,
'size' => '8536026929'
}
};
How do I access this hash with the keys sorted by size?
I tried this but I get an error saying not a hashref
foreach my $user (sort { $$stats->{$a}->{size} cmp $$stats->{$b}->{size} } keys %$stats) {
blahblahblah...
}
Your problem isn't related to sorting but to the unusual way you have defined $stats
-- namely, as a reference to a hash reference.
my %hash = (a => 1, b => 2);
my $hash_ref = {c => 3, d => 4};
my $ref_to_hash_ref = \{e => 5, f => 6};
You can use either this:
my $stats = { ... };
foreach my $user (
sort { $stats->{$a}{size} <=> $stats->{$b}{size} }
keys %$stats ) {
...
}
Or this, if you really must do the ref-to-hash-ref thing:
my $stats = \{ ... };
foreach my $user (
sort { $$stats->{$a}{size} <=> $$stats->{$b}{size} }
keys %$$stats ) {
...
}
Note also that you probably want to use <=>
(numeric comparison) rather than cmp
(string comparison).
You can pass a function to sort in order to get the values in the order you want.
#!/usr/bin/perl
use strict;
my $stats = {
'user1' => {
'files' => 281,
'size' => '3724251021'
},
'user2' => {
'files' => 555,
'size' => '7385856997'
},
'user3' => {
'files' => 235,
'size' => '3716904486'
},
'user4' => {
'files' => 578,
'size' => '8536026929'
}
};
foreach my $key (sort sortBySize (keys(%$stats)))
{
print $key, " => ", $stats->{$key}->{'files'}, " - ",
$stats->{$key}->{'size'}, "\n";
}
exit;
sub sortBySize
{
return $stats->{$b}->{'size'} <=> $stats->{$a}->{'size'};
}
OUTPUT:
user4 => 578 - 8536026929
user2 => 555 - 7385856997
user1 => 281 - 3724251021
user3 => 235 - 3716904486
If you want them sorted lowest to highest, you just need to switch the $b and $a in the sortBySize function:
return $stats->{$a}->{'size'} <=> $stats->{$b}->{'size'};
Your first line seems to be mistaken. It should be
$stats = {
Your attempt suffers from another syntax error; you need only a single sigil when dereferencing with ->
, and I believe it is better to refrain from bareword hashkeys:
foreach my $user (sort { $stats->{$a}->{'size'} cmp $stats->{$b}->{'size'} }
keys %$stats) {
# ...
}
精彩评论