2009-06-09 7 views
1

J'ai un hachage de listes qui ne sont pas remplies.Pourquoi perl "hash of lists" le fait-il?

J'ai vérifié que le bloc à la fin qui s'ajoute au hachage est en fait appelé en entrée. Il devrait soit ajouter une liste singleton si la clé n'existe pas, soit pousser vers l'arrière de la liste (référencé sous la touche droite) si c'est le cas. Je comprends que le GOTO est moche, mais je l'ai commenté et il n'a aucun effet.

Le problème est que lorsque des printhits sont appelés, rien n'est imprimé, comme s'il n'y avait pas de valeurs dans le hachage. J'ai aussi essayé chacun (% génomehits), pas de dés.

MERCI!

#!/usr/bin/perl 
use strict; 
use warnings; 

my $len = 11; # resolution of the peaks 

#$ARGV[0] is input file 
#$ARGV[1] is call number 
# optional -s = spread number from call 
# optional -o specify output file name 
my $usage = "see arguments"; 
my $input = shift @ARGV or die $usage; 
my $call = shift @ARGV or die $usage; 
my $therest = join(" ",@ARGV) . " "; 
print "the rest".$therest."\n"; 
my $spread = 1; 
my $output = $input . ".out"; 
if ($therest =~ /-s\s+(\d+)\s/) {$spread = $1;} 
if ($therest =~ /-o\s+(.+)\s/) {$output = $1;} 

# initialize master hash 
my %genomehits =(); 

foreach (split ';', $input) { 
    my $mygenename = "err_naming"; 
    if ($_ =~ /^(.+)-/) {$mygenename = $1;} 

    open (INPUT, $_); 
    my @wiggle = <INPUT>; 

    &singlegene(\%genomehits, \@wiggle, $mygenename); 

    close (INPUT); 
} 

&printhits; 

#print %genomehits; 
sub printhits { 
    foreach my $key (%genomehits) { 
     print "key: $key , values: "; 
    foreach (@{$genomehits{$key}}) { 
     print $_ . ";"; 
    } 
    print "\n"; 
    } 
} 

sub singlegene { 
# let %hash be the mapping hash 
# let @mygene be the gene to currently process 
# let $mygenename be the name of the gene to currently process 

    my (%hash) = %{$_[0]}; 
    my (@mygene) = @{$_[1]}; 
    my $mygenename = $_[2]; 

    my $chromosome; 
    my $leftbound = -2; 
    my $rightbound = -2; 

    foreach (@mygene) { 
     #print "Doing line ". $_ . "\n"; 

     if ($_ =~ "track" or $_ =~ "output" or $_ =~ "#") {next;} 

     if ($_ =~ "Step") { 
      if ($_ =~ /chrom=(.+)\s/) {$chromosome = $1;} 
      if ($_ =~ /span=(\d+)/) {$1 == 1 or die ("don't support span not equal to one, see wig spec")}; 
      $leftbound = -2; 
      $rightbound = -2; 
      next; 
     } 

     my @line = split /\t/, $_; 
     my $pos = $line[0]; 
     my $val = $line[-1]; 

     # above threshold for a call 
     if ($val >= $call) { 
      # start of range 
      if ($rightbound != ($pos - 1)) { 
       $leftbound = $pos; 
       $rightbound = $pos; 
      } 
      # middle of range, increment rightbound 
      else { 
       $rightbound = $pos; 
      } 

      if (\$_ =~ $mygene[-1]) {goto FORTHELASTONE;} 
     } 
     # else reinitialize: not a call 
     else { 
      FORTHELASTONE: 
      # typical case, in an ocean of OFFs 
      if ($rightbound != ($pos-1)) { 
       $leftbound = $pos; 
      } 
      else { 
      # register the range 
       my $range = $rightbound - $leftbound; 
       for ($spread) { 
        $leftbound -= $len; 
        $rightbound += $len; 
       } 
       #print $range . "\n"; 

       foreach ($leftbound .. $rightbound) { 
        my $key = "$chromosome:$_"; 
        if (not defined $hash{$key}) { 
         $hash{$key} = [$mygenename]; 
        } 
        else { push @{$hash{$key}}, $mygenename; } 
       } 
      } 
     } 

    } 

}
+0

Je vous recommande fortement de simplement décaler vos arguments de la pile des arguments. Techniquement les réfréner directement est plus rapide mais il est plus difficile à lire et peut avoir contribué à votre confusion ici. –

Répondre

4

Vous passez une référence à %genomehits à la fonction singlegene, puis le copier dans un nouveau hachage quand vous faites my (%hash) = %{$_[0]};. Vous ajoutez ensuite des valeurs à %hash qui disparaît à la fin de la fonction.

Pour résoudre ce problème, utilisez la référence directement avec la notation fléchée. Par exemple.

my $hash = $_[0]; 
... 
$hash->{$key} = yadda yadda; 
+0

merci beaucoup; J'utilisais des références comme ça avant mais perl m'a dit que c'était une sémantique déconseillée. N'écoutez jamais le compilateur! – Overflown

+0

Je suis très surpris, Perl vous l'a dit. Pour autant que je sache, ce n'est pas du tout obsolète. –

+0

$ hash -> {$ key} == $ {$ hash} {$ clé} == $$ hash {$ clé}; certaines personnes aiment # 2 ou # 3 plus que # 1. # 1 est le plus commun, mais # 3 a l'avantage d'être facilement interpolé dans les chaînes. – ephemient

2

Je pense qu'il est cette ligne:

my (%hash) = %{$_[0]}; 

vous passez dans une référence, mais cette déclaration fait une copie de votre hachage. Tous les ajouts que vous faites dans singlegene sont perdus lorsque vous revenez. Laissez-le comme une référence de hachage et cela devrait fonctionner. PS-Data :: Dumper est votre ami lorsque de grandes structures de données ne se comportent pas comme prévu. Je répandrai quelques-uns de ceux-ci dans votre code ...

use Data::Dumper; print Dumper \%genomehash;