Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Sorted tied hash wierdness

by genecutl (Beadle)
on Nov 18, 2003 at 23:45 UTC ( #308188=perlquestion: print w/replies, xml ) Need Help??

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

I just got done writing and debugging some code which made use of a sorted tied hash using DB_File BTREE. I was getting weird results which I was able to track down to my custom sorting algorithm. Shown below is the pared-down code containing both the working and non-working versions of the sorting algorithm:
use Fcntl; use DB_File; my $db_file = '/tmp/db_file'; unlink $db_file if -e $db_file; my $btree_info = new DB_File::BTREEINFO; $btree_info->{'flags'} = R_DUP; my $comparison_type = shift @ARGV; if (! $comparison_type) { # this method works $btree_info->{'compare'} = sub { my($a,$b) = @_; $a <=> $b }; } else { # this method does not work $btree_info->{'compare'} = sub { $_->[0] <=> $_->[1] }; } $tied_hash_obj = tie( %tied_hash, 'DB_File', $db_file, O_RDWR|O_CREAT, + 0640, $btree_info ) or die "Can't tie tied_hash to $db_file: $!"; for ( 0 .. 20) { $tied_hash{rand(100)} = ++$i; } my ($status, $k, $v); for ( $status = $tied_hash_obj->seq($k, $v, R_FIRST); $status == 0; $status = $tied_hash_obj->seq($k,$v, R_NEXT) ) { push @vals_sorted_by_keys, $v; push @sorted_keys, $k; } print join("\n", @vals_sorted_by_keys),"\n********\n"; print join("\n", @sorted_keys),"\n";
Comparing $_->[0] and $_>[1] directly, leads to all the keys coming out equal to the very first key. Saving $_>[0] and $_>[1] to temporary variables eliminates this problem. Can someone explain this?

Replies are listed 'Best First'.
Re: Sorted tied hash wierdness
by Chmrr (Vicar) on Nov 18, 2003 at 23:49 UTC

    You're getting too reference-happy. $_->[0] isn't the same as $_[0] -- the former treats $_ as an array ref, and takes the 0th element of that, while the second takes the 0th element of the @_ array. In this case, it's the latter you want. Change sub { $_->[0] <=> $_->[1] } to sub { $_[0] <=> $_[1] } and you'll have more luck.

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

      You're absolutely right. Don't you hate it when you waste time on something that should be completely obvious? Thanks!
Re: Sorted tied hash wierdness
by Roger (Parson) on Nov 19, 2003 at 00:03 UTC
    You can change the line:
    $_->[0] <=> $_->[1]
    $_[0] <=> $_[1]
    @_->[0] <=> @_->[1]
    and even insanely to
    @{[shift]}->[0] <=> @{[shift]}->[0]
    And it will work.

    The last last solution is highly perl implementation dependent, it will not work if the order of evaluation changes in the future. I came up with it just to see if I could compare two shift's directly for fun. And yes it works. :)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://308188]
Approved by cleverett
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (2)
As of 2021-05-13 04:20 GMT
Find Nodes?
    Voting Booth?
    Perl 7 will be out ...

    Results (134 votes). Check out past polls.