Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

How to make a array of hashes and search them

by Anonymous Monk
on Feb 17, 2012 at 10:29 UTC ( [id://954496]=perlquestion: print w/replies, xml ) Need Help??

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

Hello i am deepak.

I have 5 files. First file contains unique IDs. Rest of the four files contain unique ID and a value. I have take to IDs from the first file and search it in all four files. If the ID is present print the corresponding value. example output is given below

ID val1 val2 val3 val4

ID - the ID searched, val1 - if present value from 1st file else 0, similiarly for file 2 file 3 and file 4.

Hope i made my question clear..?? Please help

  • Comment on How to make a array of hashes and search them

Replies are listed 'Best First'.
Re: How to make a array of hashes and search them
by moritz (Cardinal) on Feb 17, 2012 at 10:35 UTC

    I think you are looking for code roughly like this:

    my %IDs; # when reading the ID file, for each line do something like $IDs{$current_id} = []; # and then for each line in the four other files: while (my $line = <$file>) { my ($id, $value) = split / /, $line; push @{$IDs{$id}}, $value } # and at the very end, print them all out: for my $id (sort keys %IDs) { print "$id: ", join(', ', @{$IDs{$id}}), "\n"; }

    See also: perlintro, perlreftut.

    If you want to keep track about which file contains which ID, you should use something like $IDs{$id}[$file_number] = $value instead of using push.

Re: How to make a array of hashes and search them
by Anonymous Monk on Feb 17, 2012 at 10:42 UTC
Re: Searching Multiple files and print it in order
by JavaFan (Canon) on Feb 17, 2012 at 10:46 UTC
    You can do this in the shell:
    grep -F -f file1 file2 file3 file4 file5
    Although this assumes that an ID will not match a value.

    Untested Perl solution:

    my %matches = map {/(.*)/, 1}, do {local @ARGV = "file1"; <>}; local @ARGV = ("file2", "file3", "file4", "file5"); while (<>) { /^(\S+)/ && $matches{$1} && print }
Re: How to make a array of hashes and search them
by Anonymous Monk on Feb 17, 2012 at 17:30 UTC

    Thanks a ton for the help. I wrote as per the pseudo code. it worked but here the problem is for each and every ID its print same values in all four columns. I have no clue why it is happening.so i need more help.

    Thanking you in advance.

    Regards

    Deepak

    foreach $file (@files) { open(INP,"$file") or die "Cannot open file :$!\n"; while (<INP>) { chomp; @line = split "\t",$_; if(exists $trans{$line[0]}) { $array[$j] = $line[1]; $trans{$line[0]} = \@array; } } close(INP); $j++; } foreach $key (keys %trans) { print OUT "$key\t"; foreach(@{$trans{$key}}) { print OUT "$_\t"; } print OUT "\n"; }

      There seems to be only one global variable with name @array. Thus \@array always returns a reference to the same array, which is probably not what you want.

      The solution is to use strict; and declare your variables in appropriate scopes.

      As moritz said, your @array appears to be global, so it's not getting recreated each time through your loop, and all your hash keys are getting assigned a reference to the same array. Here's how I'd rewrite your loop to eliminate that array and clarify some things:

      my $j = 0; # file/column number foreach $file (@files){ open(INP,"$file") or die "Cannot open file :$!\n"; while (<INP>){ chomp; my($key,$value) = split "\t"; if(exists $trans{$key}){ $trans{$key}[$j] = $value; } } close(INP); $j++; }

      When you split a line into an array and then start accessing the elements directly like $line[0], that's a good sign you might want to split it into named scalars like $key and $value instead, so you don't have to remember later what array index held what. I think it also makes it easier to see what I'm doing there when I assign the $value to the $j-th element of the array pointed to by the $key of the hash.

      Aaron B.
      My Woefully Neglected Blog, where I occasionally mention Perl.

Re: How to make a array of hashes and search them
by Anonymous Monk on Feb 18, 2012 at 00:19 UTC
    You can set up "arrays of hashes" or "hashes of arrays" or "anything of anything" because in every case the "thing" that is "in the (array or hash)" is either a "scalar" or "a reference." The magic bean here is, "a reference," because "a reference" can refer to anything. An array, a hash, or even for that matter another reference or a scalar. Very complex structures are built one brick at a time.
Re: How to make a array of hashes and search them
by pdeepak (Initiate) on Feb 17, 2012 at 11:11 UTC

    Thank you moritz.

    Ya the code works fine but the problem is with the IDs which are not present in say two of the files. I want to print the value as 0. So if the file 1 and file 3 have an id present and its absent in 2 and 4. it should print

    ID </t> value1 <\t> 0 <\t> value3 <\t> 0 <\n>.

    The other thing is i want to know how can i iterate through files and make the hashes..??

    sorry for the trouble

      In that case, what you probably want is a hash of arrays, rather than an array of hashes. You want a hash keyed on the unique IDs in your first file, and values consisting of 4-element arrays. Then you can loop through your hash a second time and print out all key/value pairs that have something other than zero in one of their value elements.

      Give that a shot, and if you have trouble, post the code so we can help with it. Pseudo-code would look something like this:

      instantiate a hash open file of unique keys while read a line get the key from it make it a key in your hash, with its value being a reference to an a +rray containing four zeros for N = 1 to 4 open file1 while read a line split the key and value out of it if the key exists in your hash assign the value to your hash as the Nth element of an array + referred to by this key if the key doesn't exist skip it or error, depending on your design for each key in the hash if any of its array's elements are non-zero print the key and array elements joined by tabs

      Aaron B.
      My Woefully Neglected Blog, where I occasionally mention Perl.

A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (10)
As of 2024-04-18 10:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found