N
Niall Macpherson
I have a problem sorting a hash by value rather than key. I have read
the FAQ concerning this but unfortunately it does not help . I am not
sure if this is due to with my misunderstanding of the way the sort
function works or due to me not using the correct data structure.
I have a number of database spaces each of which has a unique name
which I am using as the hash key . Each key has a size, used and free
attribute associated with it . So a typical entry would look like
$dbspaces{space67}{size} = 12345;
$dbspaces{space67}{used} = 123;
$dbspaces{space67}{free} = 12222;
I wish to sort the hash based on the 'used' value.
I do understand that I cannot sort the hash directly , I have to sort
the keys and then access the hash by the sorted keys - this is fine.
I do understand also that it may be better to use a hash of arrays ,
although I would prefer to be accessing $dbspaces{space67}{size} than
$dbspaces{space67}[0] for readability.
My problem is that I do not seem to be able to access the hash within
the sort function.
i.e if I use the format
my @sort_by_used_keys = sort sort_by_used (keys %dbspaces);
the sort function 'sort_by_used()' only has access to the $a and $b
variables, not the hash itself.
All the examples I have seen which access the hash itself seem to do so
using the 'inline' (hope that is the correct terminology) version of
sort - e.g
@sorted = sort { lc($hash{$a}) cmp lc($hash{$b}) } keys %hash;
Attached is a very cut down version of the code. It will compile and
run although it will not do anything since the 'sort_by_used' function
cannot access the hash and I therefore cannot perform the correct tests
within this function I would be grateful if someone could tell nme
what I am doing wrong.
Many thanks
use strict;
use warnings;
use Data:umper;
##--------------------------------------------------------------
sub sort_by_used
{
## How do I access the hash here ?
# This will not compile
#return ($dbspaces{$a}{used} <=> dbspaces{$b}{used})
return(0);
}
##--------------------------------------------------------------
##
## Note - cannot sort a hash directly.
##
## Need to sort the hash keys and then access the hash
## via the sorted array
##--------------------------------------------------------------
my %dbspaces = ();
my $key = "";
## Populate the hash
while(<DATA>)
{
chomp;
my @vals = split;
$key = $vals[0];
$dbspaces{$key}{size} = $vals[1];
$dbspaces{$key}{used} = $vals[2];
$dbspaces{$key}{free} = $vals[3];
}
print Dumper %dbspaces;
## Sort by the used attribute
my @sort_by_used_keys = sort sort_by_used (keys %dbspaces);
## Access the hash by the sorted keys, i.e used descending
foreach $key (@sort_by_used_keys)
{
print Dumper $dbspaces{$key};
}
exit(0);
__END__
space1 100 63 37
space2 200 12 188
space47 300 299 1
space99 400 375 25
the FAQ concerning this but unfortunately it does not help . I am not
sure if this is due to with my misunderstanding of the way the sort
function works or due to me not using the correct data structure.
I have a number of database spaces each of which has a unique name
which I am using as the hash key . Each key has a size, used and free
attribute associated with it . So a typical entry would look like
$dbspaces{space67}{size} = 12345;
$dbspaces{space67}{used} = 123;
$dbspaces{space67}{free} = 12222;
I wish to sort the hash based on the 'used' value.
I do understand that I cannot sort the hash directly , I have to sort
the keys and then access the hash by the sorted keys - this is fine.
I do understand also that it may be better to use a hash of arrays ,
although I would prefer to be accessing $dbspaces{space67}{size} than
$dbspaces{space67}[0] for readability.
My problem is that I do not seem to be able to access the hash within
the sort function.
i.e if I use the format
my @sort_by_used_keys = sort sort_by_used (keys %dbspaces);
the sort function 'sort_by_used()' only has access to the $a and $b
variables, not the hash itself.
All the examples I have seen which access the hash itself seem to do so
using the 'inline' (hope that is the correct terminology) version of
sort - e.g
@sorted = sort { lc($hash{$a}) cmp lc($hash{$b}) } keys %hash;
Attached is a very cut down version of the code. It will compile and
run although it will not do anything since the 'sort_by_used' function
cannot access the hash and I therefore cannot perform the correct tests
within this function I would be grateful if someone could tell nme
what I am doing wrong.
Many thanks
use strict;
use warnings;
use Data:umper;
##--------------------------------------------------------------
sub sort_by_used
{
## How do I access the hash here ?
# This will not compile
#return ($dbspaces{$a}{used} <=> dbspaces{$b}{used})
return(0);
}
##--------------------------------------------------------------
##
## Note - cannot sort a hash directly.
##
## Need to sort the hash keys and then access the hash
## via the sorted array
##--------------------------------------------------------------
my %dbspaces = ();
my $key = "";
## Populate the hash
while(<DATA>)
{
chomp;
my @vals = split;
$key = $vals[0];
$dbspaces{$key}{size} = $vals[1];
$dbspaces{$key}{used} = $vals[2];
$dbspaces{$key}{free} = $vals[3];
}
print Dumper %dbspaces;
## Sort by the used attribute
my @sort_by_used_keys = sort sort_by_used (keys %dbspaces);
## Access the hash by the sorted keys, i.e used descending
foreach $key (@sort_by_used_keys)
{
print Dumper $dbspaces{$key};
}
exit(0);
__END__
space1 100 63 37
space2 200 12 188
space47 300 299 1
space99 400 375 25