yucani has asked for the wisdom of the Perl Monks concerning the following question:

Hi, i am writing some code and moving subroutines to a package. By this i encountered following problem when sorting hashes by value. The values itself is a line from a CSV file. To get the value from the line i am using a function grabdataentry, which takes the hash by ref, gets the key and the entry position of the value to sort by. Here the source:
sub grabdataentry { my $href=shift; my %dhash=%{$href}; my $skey=shift; my $pos=shift; my @list=split /;/, $dhash{$skey}; return $list[$pos]; }
When hiding this sub in package and calling like this
foreach my $key (sort { grabdataentry(\%hash,$a,0) cmp grabdataentry +(\%hash,$b,0) } keys %hash)
it does not work anymore. If the sub stays inside the caller package it works. Whats wrong?



May PERL live as long the last F77 program runs.

Replies are listed 'Best First'.
Re: hash ref package
by MidLifeXis (Monsignor) on Sep 14, 2012 at 18:01 UTC

    Can you define 'does not work anymore'?

    One possible cause: if you move it to a different package and don't export the sub into the namespace of the caller, sort won't know where to find it. If this particular cause of 'does not work anymore' is the reason, then specifying the full class of the grabdataentry sub or importing it into your caller's namespace may help.

    --MidLifeXis

      You are right, as the function was not seen, only the foreach loop stoped working but no (visible) error or warning has been produced. Thanks for pushing me in the right direction. Solved.
Re: hash ref package
by Anonymous Monk on Sep 14, 2012 at 21:11 UTC

    May I recommend the Schwartzian transform for your sort? (it looks extremely inefficient.)

    map { $_[0] } sort { $a->[1] cmp $b->[1] } map { [ $_, grabdataentry(\%hash, $_, 0) ] } keys %hash;

    Anyway, it may not be a problem if you have fewer than (let's say) fifty keys, but after that it'll take quite a bit of cpu. Oh, and please don't copy the hash in the subroutine either:

    sub grabdataentry { my $href=shift; ... my @list=split /;/, $href->{$skey};

    By copying the hash to %dhash you're saving two whole keystrokes.