Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

hash of hashes

by Anonymous Monk
on Nov 23, 2006 at 11:02 UTC ( [id://585698]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Monks, I am having huge probelms with HoH. I have a list of files which i would like to process and make the HoH from.
$refine =1; use File::Find; find(\&wanted, 'upload_profile/'); sub wanted { #/\_$refine/ && print "$File::Find::name\n" && push @a +rray, $_; /predictions\_\Q$refine\E/i && push @found, $_; } ####sort array of foud files### @find = sort { $a cmp $b } @found; #print "find: @find"; foreach my $file (@find) { print "file: $file\n"; open (LOOKUP, "<upload_profile/$file") or die $!; while (<LOOKUP>) { ($name, $id) = (split m{\t})[3, 4]; print "id: $id\n"; $data{$file}{$id} = $name; } close (LOOKUP); } close (LOOKUP);
I want to search the HoH using one of the specific files used to make the HoH. I have another file which i would like to use to search against the HoH which is a list of ids 1-1000.
$file = 'test_predictions_1'; open (FH, "<EXAMPLE"); while (<FH>) { $id = $_; if (exists $data{$file}{$id}) {print "match\n";} }
However, this doesnt seem to work. Thanks for your help

Replies are listed 'Best First'.
Re: hash of hashes
by shmem (Chancellor) on Nov 23, 2006 at 11:18 UTC
    Perhaps this works:
    $file = 'test_predictions_1'; open (FH, "<EXAMPLE"); while (<FH>) { chop; # remove trailing newline $id = $_; if (exists $data{$file}{$id}) {print "match\n";} }

    <update>

    Having a second look at your code:

    if (exists $data{$file}{$id}) {print "match\n";}

    Does the key $file to the hash $data even exist in the hash?

    You could use Data::Dumper to dump your HoH and check if it's what you expect.

    </update>

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      i have done he following:
      foreach my $file (@find) { print "file: $file\n"; open (LOOKUP, "<upload_profile/$file") or die $!; while (<LOOKUP>) { ($name, $id) = (split m{\t})[3, 4]; #print "id: $id\n"; #$data{$file} = {$id => $refName}; $data{$file}{$id} = $name; } } close (LOOKUP); for $file ( keys %data ) { print "$file: "; for $role ( keys %{ $data{$file} } ) { print "$id=$data{$file}{$id} "; } print "\n"; }
      but it seems to return only the last line of each file

        Data::Dumper is your friend. I suspect you will find that if you Dump out %data between your first loop and your second, that you will find that you're storing more than the last line of each file. However strict is even more your friend, and could have saved you the time in posting on here.

        If your second loop is a direct cut-n-paste then your error should be easily fixed. The following line:

        print "$id=$data{$file}{$id} ";

        Should probably be:

        print "$role=$data{$file}{$role} ";

        If you were using strict, Perl would have told you about this.

        The following code works for me.

        use strict; my %data; foreach my $file (@ARGV) { print "file: $file\n"; open (LOOKUP, "$file") or die $!; while (<LOOKUP>) { chomp; my ($name, $id) = (split m{\t})[3, 4]; $data{$file}{$id} = $name; } close (LOOKUP); } for my $file ( keys %data ) { print "$file: "; for my $role ( keys %{ $data{$file} } ) { print "$role=$data{$file}{$role} "; } print "\n"; }

        Be aware that if any id is repeated in the file for a different name, then you will only get the last unique pair. For example if your file contains:

        xxx yyyy Fred 4 zzzz wwww James 4

        Then you will only get the James => 4 pairing and Fred will be lost. If this is a problem, then you'll need to use an array reference:

        use strict; my %data; foreach my $file (@ARGV) { print "file: $file\n"; open (LOOKUP, "$file") or die $!; while (<LOOKUP>) { chomp; my ($name, $id) = (split m{\t})[3, 4]; push @{$data{$file}{$id}}, $name; } close (LOOKUP); } for my $file ( keys %data ) { print "$file: "; for my $role ( keys %{ $data{$file} } ) { for my $name ( @{$data{$file}{$role}} ) { print "$role=$name "; } } print "\n"; }

        Hope this helps.

      i have tried chomp and chop before posting with no success
Re: hash of hashes
by themage (Friar) on Nov 23, 2006 at 11:22 UTC
    Hi,

    What, specificly don't work?

    Do you have a file called 'test_predictions_1', that have ids in the range 1 to 1000?

    Are the print "file: $file\n"; and print "id: $id\n"; printing what you expect?

    Why do you have a second close (LOOKUP); outside the foreach loop?

    Can you provide us some specific data that you think should work and is not working?

Re: hash of hashes
by l.frankline (Hermit) on Nov 23, 2006 at 11:22 UTC

    hi,

    As per my views, I would like to tell you my suggestion is:

    At the end, you are reading an input file call "EXAMPLE", and fetching each line by line, while doing so, In the code, $id = $_; what happens is $_ is the default variable which carries a trailing record separator from a string, so you have to remove that by using chomp function. that will work.

    Bye

    Don't put off till tomorrow, what you can do today.

      this is my complete code:
      use File::Find; find(\&wanted, 'upload_profile/'); sub wanted { #/\_$refine/ && print "$File::Find::name\n" && push @a +rray, $_; /predictions\_\Q$refine\E/i && push @found, $_; } ####sort array of foud files### @find = sort { $a cmp $b } @found; #print "find: @find"; foreach my $file (@find) { print "file: $file\n"; open (LOOKUP, "<upload_profile/$file") or die $!; while (<LOOKUP>) { ($name, $id) = (split m{\t})[3, 4]; print "id: $id\n"; $data{$file}{$id} = $name; } close (LOOKUP); } close (LOOKUP); open (dig_go, "<check.txt"); while (<dig_go>) { ($id, $name, $file_disappeared, $enzyme_one, $target_one, $enzyme_two, + $target_two, $enzyme_three, $target_three, $enzyme_four, $target_fou +r, $enzyme_five, $target_five) = split (m/\t/); ##tried chomp on each if (exists $data{$file_disappeared}{$id}) {print "match\n";} }
        this is my complete code:

        Well, what happened to  $refine =1; ? Where's the  use strict; and the  use Data::Dumper; that others suggested earlier? (In other words, if you think this is the whole script, you're wrong.) When you do this:

        while (<LOOKUP>) { ($name, $id) = (split m{\t})[3, 4]; print "id: $id\n"; $data{$file}{$id} = $name; }
        is it possible that the "$id" string (fifth tab-delimited field on each line of $file) is at the end of the line? If so, that would mean that there's a "\n" (or "\r\n") included in the value of $id.

        If you've already tried chop and chomp to no avail, try this instead:

        s/[\r\n]+$//;
        That can be handy for cases where you are reading data files that come from some OS other than the one your script is running on. Do that both inside the  while <LOOKUP> loop and inside the  while <dig_go> loop.

        Apart from that, if you'll start applying some of the advice you've already been given (use strict, use Data::Dumper), problems will be easier to diagnose, and you should be able to find the problem on your own. You might also want to use the perl debugger (start your script with  perl -d script_file), set break points inside each of those while loops, and see what's going on (cf. perldebtut and perldebug).

        If your script has  use Data::Dumper;, you can say  p Dumper(\%data) as a debugger command, to see what's in your hash structure, as well as just  p to print the current value of $_ (whatever was just read from a file). Very handy, and really simple. Do that.

        check.txt looks llike:
        1055 something test_predictions_1 info 1010 0 0 + 0 0 0 0 0 0

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (2)
As of 2024-03-19 05:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found