Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Strange Behaviour of Two Hashes

by monkfan (Curate)
on May 17, 2005 at 13:38 UTC ( [id://457797]=perlquestion: print w/replies, xml ) Need Help??

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

Most Revered Monks,
I wonder what's wrong with my code below. I can't see anything abnormal in placing the 'print' and subroutine after the "foreach(@test) block". But it gives a strange behaviour. It prints empty hashes after moving them. Here is the code:

Update: Subroutine included as requested. Also, before posting I have already reduced the code as simple as possible for test case. This is the simplest I can get.
#!/usr/bin/perl -w use strict; use Data::Dumper; my @freq_set = ( [ '3 A B', '2 A H', '3 A C', '4 A D', '2 B C', '2 B D', '2 C H', '4 C D', '2 D H' ], # There are some other array set # So yes, this is meant to be an AoA ); my $hash = { 'S1' => [ 'A', 'B', 'C','D','H','A' ], 'S2' => [ 'A', 'C', 'D','B','G','J' ], 'S3' => [ 'C', 'A', 'D','H','M','K' ], 'S4' => [ 'A', 'B', 'I','C','I','D' ] }; # These 3 lines have strange behaviour # If you move these three lines after foreach(@test) block # it will print nothing, but here it prints the correct answer my $seq = 'C D'; my %alignment = align($hash,$seq); print Dumper \%alignment; #-------Begin Loop--------------- my @test; foreach my $f ( 0 .. $#freq_set ) { foreach my $m ( 0 .. $#{$freq_set[$f]} ) { my ($sp,$mt) = $freq_set[$f][$m] =~/(\d+)\s+(.*)/; push @test, $mt; } } my %aln; foreach ( @test ) { $aln{$_} = { align($hash,$_) }; } #---------BEGIN Strange Behavior-------------- # If you move above three lines here then, # it print *empty* hashes for both of Dumper print. Why? print "From LOOP\n"; print Dumper $aln{'C D'}; #------------ Subroutine --------------- sub align { my ($hashref,$seq) = @_; my @in = split(/\s/,$seq); my $test = join('(.*?)',@in); my %hyph_padded_seq; my %sequences; my $reduce; for (keys %$hashref) { $reduce = length(${$hashref->{$_}}[0]); last; } for my $key( sort {$a cmp $b} keys(%$hashref)) { my $string = join('_',@{$hashref->{$key}}); if($string =~ $test) { $sequences{$key} = $hashref->{$key}; } } my $regex = '.*'.join('(.*)',@in).'.*'; my %in_the_running; my $biglen = 0; foreach my $seq (keys %sequences) { my @dum_in_the_running; my @letters = @{$sequences{$seq}}; #s/.*($in[0].*$in[$#in]).*/$1/; my ($first, $last) = (0,0); for (@letters) { last if $_ eq $in[0]; $first++; } for (reverse @letters) { last if $_ eq $in[$#in]; $last++; } $last = $#letters - $last; @letters = @letters[$first..$last]; my $asstr = join('',@letters); if ((my @gaps) = ($asstr =~ m/$regex/o)) { my $len = length(join('',@gaps)) / $reduce; if ($len > $biglen) { unshift(@dum_in_the_running, @letters ); $in_the_running{$seq} = [@dum_in_the_running]; $biglen = length(join('',@gaps)); } elsif ($len == $biglen) { unshift(@dum_in_the_running, @letters ); $in_the_running{$seq} = [@dum_in_the_running]; } else { push(@dum_in_the_running, @letters ); $in_the_running{$seq} = [@dum_in_the_running]; } } } #print Dumper \%in_the_running; if ( %in_the_running ) { my @keys_from_bigap = ( sort { @{$in_the_running{$b}} <=> @{$in_the_running{$a}} } keys %in_the_running ); $hyph_padded_seq{$keys_from_bigap[0]} = join('',@{$in_the_running{$ +keys_from_bigap[0]}}); my @base = @{$in_the_running{$keys_from_bigap[0]}}; for my $seqno (1..$#keys_from_bigap) { # my @seq = split(//,$in_the_running[$seqno]); my @seq = @{$in_the_running{$keys_from_bigap[$seqno]}}; my $count = $#base; my @disp; for my $q (reverse @base) { # Add this condition, when query is only 1 push(@seq,'-' x $reduce) if (!$seq[$#seq]); if (($seq[$#seq] eq $q) || ($count == $#seq)) { push(@disp, pop(@seq)); } else { push(@disp, '-' x $reduce); } $count--; } $hyph_padded_seq{$keys_from_bigap[$seqno]} = join('', revers +e(@disp)); } } return %hyph_padded_seq; }
To save space, I have stored the subroutine 'align' here. Could it be a problem with the subroutine?
Regards,
Edward

Replies are listed 'Best First'.
Re: Strange Behaviour of Two Hashes
by holli (Abbot) on May 17, 2005 at 13:59 UTC
    Always post all *relevant* code. If the code is too long, use readmore-tags. In this case the align subroutine is the one that alters your hashes, as it seems, and thus relevant. And no. I will not follow the link to get it.

    This mainly because of my laziness, but also for the sake of node completeness. What if the url is dead in some time? Nothing is as old as the url from yesterday.


    holli, /regexed monk/
Re: Strange Behaviour of Two Hashes
by dragonchild (Archbishop) on May 17, 2005 at 14:00 UTC
    To elaborate on holli's excellent comments, you need to reduce this to as simple a testcase as possible. Right now, there's too much code to work through - starting removing stuff until you remove the bug, add the thing you just removed, and that's where the bug is.

    • In general, if you think something isn't in Perl, try it out, because it usually is. :-)
    • "What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?"
Re: Strange Behaviour of Two Hashes
by radiantmatrix (Parson) on May 17, 2005 at 14:53 UTC

    Something is awry with your particular Perl setup, I think. I ran your code verbatim, and got the following output:

    $VAR1 = { 'S1' => 'C-D', 'S2' => 'C-D', 'S4' => 'CID', 'S3' => 'CAD' }; From LOOP $VAR1 = { 'S1' => 'C-D', 'S2' => 'C-D', 'S4' => 'CID', 'S3' => 'CAD' };

    Is something wrong with this? For reference:

    This is perl, v5.8.6 built for MSWin32-x86-multi-thread

    The Eightfold Path: 'use warnings;', 'use strict;', 'use diagnostics;', perltidy, CGI or CGI::Simple, try the CPAN first, big modules and small scripts, test first.

Re: Strange Behaviour of Two Hashes
by BrowserUk (Patriarch) on May 17, 2005 at 15:03 UTC

    Strange? I cannot reproduce your reported behaviour. This is the output I get from your code:

    P:\test>457797 $VAR1 = { 'S1' => 'C-D', 'S2' => 'C-D', 'S4' => 'CID', 'S3' => 'CAD' }; From LOOP $VAR1 = { 'S1' => 'C-D', 'S2' => 'C-D', 'S4' => 'CID', 'S3' => 'CAD' };

    Is that what you are expecting?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
      Hi BrowserUk,
      Thanks for answering. As I have commented inside the code. you will see the problem, only after you move those three lines after the "foreach(@test)" block. Please try it.
      It should print this:
      $VAR1 = {}; From LOOP $VAR1 = {};
      Regards,
      Edward

        Hmmm. I copied them this time rather than moved them which explains the error messages:

        P:\test>457797 "my" variable $seq masks earlier declaration in same scope at P:\test\ +457797.pl line 37. "my" variable %alignment masks earlier declaration in same scope at P: +\test\457797.pl line 38. $VAR1 = { 'S1' => 'C-D', 'S2' => 'C-D', 'S4' => 'CID', 'S3' => 'CAD' }; $VAR1 = { 'S1' => 'C-D', 'S2' => 'C-D', 'S4' => 'CID', 'S3' => 'CAD' }; From LOOP $VAR1 = { 'S1' => 'C-D', 'S2' => 'C-D', 'S4' => 'CID', 'S3' => 'CAD' };

        But I still don't see the problem?


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re: Strange Behaviour of Two Hashes
by buckaduck (Chaplain) on May 17, 2005 at 23:03 UTC
    The error is on line 109: if ((my @gaps) = ($asstr =~ m/$regex/o)) The /o in your regex is telling Perl to compile the regular expression only once because the string $regex is never going to change. But it does change, because you call the subroutine more than once. Therefore, the regex gets compiled differently, depending on which call to the align() subroutine occurs first.

    The way to fix it is to remove the /o from the regex: if ((my @gaps) = ($asstr =~ m/$regex/))

    buckaduck

Re: Strange Behaviour of Two Hashes
by Aragorn (Curate) on May 17, 2005 at 14:45 UTC
    Could it be a problem with the subroutine?
    That's very possible. I have no idea what it is supposed to do. It's almost 100 lines long, maybe you should try and split it up in more manageable chunks. More descriptive variable names and maybe some comments why you are doing things at key places will also help.

    Arjen

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://457797]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (8)
As of 2024-04-24 10:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found