CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
How to populate a Hash

 



vikas.deep
User

May 13, 2009, 9:59 PM

Post #1 of 17 (2019 views)
How to populate a Hash Can't Post

A very basic question . The following code works fine
#! /usr/bin/perl -w
use strict;
use warnings;
{
my %h;
$h{orange} = "orange";
$h{apple} = "red";
print $h{apple}
}
# output is red
Problem arises if I have a large number of key-value pairs and I try to populate key-value pairs using two separate files
#! /usr/bin/perl -w
use strict;
use warnings;
{
my %h;
my $value;
open (my $FH,"keys") or die "cannot open the file $!";
open (my $FHH,"values") or die "cannot open the file $!";
while (<$FH>)
{
$value = <$FHH>;
$h{$_} = "$value" ;
}
print %h,"\n";
print keys %h, "\n";
print values %h;
print $h{apple}
}
Here %h is alright!
keys %h is alright!
values %h is alright!
BUT $h{apple} is NOT!!

# File keys has
#orange
#tomato
#banana
#apple

#File values has
#apple
#orange
#yellow
#red

In the second example %h is created as is clear by print keys or value %h but I cannot access particular values?
#####OUTPUT ####
[root@localhost Documents]# perl arrpop.pl
apple
red
tomato
orange
orange
apple
banana
yellow

apple
tomato
orange
banana

red
orange
apple
yellow
Use of uninitialized value in print at arrpop.pl line 18, <$FH> line 4.
-For all my suggestions " I am sure someone else can do it in a better or elegant manner!"


alex_v2
User

May 14, 2009, 12:19 AM

Post #2 of 17 (2011 views)
Re: [vikas.deep] How to populate a Hash [In reply to] Can't Post

2 quick things. One may answer your question the second just a note.

try $h{'apple'}. you should not use "bare" words when accessing hash keys.

the other is that use warnings is not necessary when you have #!/usr/bin/perl -w as that tells it to use perl with warnings.

-Alexander


vikas.deep
User

May 14, 2009, 12:34 AM

Post #3 of 17 (2009 views)
Re: [alex_v2] How to populate a Hash [In reply to] Can't Post

The warning part is a minor thing just leave it aside or delete use warnings whateve I have use $h{'apple'}, $h{"apple"}, $h{-apple} but agai the same result
"Use of uninitialized value in print at arrpop.pl line 18, <$FH> line 4."
The problem is that computer knows there is a hash %h and what are it's keys and values and it is printing keys %h and values%h but I can't access the values using $h{'$key'}!!
Computer knows $h{apple} is red but it won't print out !!!
-For all my suggestions " I am sure someone else can do it in a better or elegant manner!"


alex_v2
User

May 14, 2009, 12:50 AM

Post #4 of 17 (2004 views)
Re: [vikas.deep] How to populate a Hash [In reply to] Can't Post

Ok I wrote a test file using you example files and to my amazement got a very similar error and traced it down to the lines from the file not being chomped. Here is the code I came up with that returned fine. Hope it helps.


Code
#!/usr/bin/perl -w 

use strict;

open(FILE1, '<file1') || die $!;
my @keys = <FILE1>;
chomp(@keys);
close(FILE1);
open(FILE2, '<file2') || die $!;
my @values = <FILE2>;
chomp(@values);
close(FILE2);

my %h;

@h{@keys} = @values;

print qq($h{'apple'}\n);


-Alexander


vikas.deep
User

May 14, 2009, 1:07 AM

Post #5 of 17 (2000 views)
Re: [alex_v2] How to populate a Hash [In reply to] Can't Post

Thanks it is working Actually I also tried chomp but then my computer was saying there is some problem in chomping and i thought that one can only chomp scalars and not arrays.
In your code the following is not clear you have not declared or initialized a array @h. h is a hash not array but still the computer is not complaining and code is working
Secondly I don't think qq() is required just $h{"key "} is working fine.

"@h{@keys} = @values; "
Many thanks for your helpSmile
-For all my suggestions " I am sure someone else can do it in a better or elegant manner!"


KevinR
Veteran


May 14, 2009, 1:29 AM

Post #6 of 17 (1998 views)
Re: [alex_v2] How to populate a Hash [In reply to] Can't Post


In Reply To
2 quick things. One may answer your question the second just a note.

try $h{'apple'}. you should not use "bare" words when accessing hash keys.

the other is that use warnings is not necessary when you have #!/usr/bin/perl -w as that tells it to use perl with warnings.


Actually hash keys are a special case and it is OK to not quote keys that don't have any non-word characters. Keys with non-word characters can still possibly be unquoted but can produce warnings so it best to always quote keys with non-word characters.
-------------------------------------------------


(This post was edited by KevinR on May 14, 2009, 2:19 AM)


alex_v2
User

May 14, 2009, 2:11 AM

Post #7 of 17 (1995 views)
Re: [vikas.deep] How to populate a Hash [In reply to] Can't Post

Alright I will try to explain this as best I can for the whole @h deal.

when you call a hash with @h{} it is actually just telling the hash to become what is called slices which is just a fancy way of telling the hash to expect a list of values and keys instead of just one key value pair. The {} following the variable is actually declaring it as a hash. Hope that clears that up a little bit anyways.

For the second part you are right qq() or "" is not required around the print and just as Kevin has pointed out as long as a key does not contain non word characters. Here is the reason I tend to practice quoting everything. "" or qq() is not always required but always works where as not using them sometimes works and sometimes does not. So for me quoting has become habit though it is not always required.

Glad I could be of some help and hope you stick around on the boards.

-Alexander


KevinR
Veteran


May 14, 2009, 2:22 AM

Post #8 of 17 (1992 views)
Re: [vikas.deep] How to populate a Hash [In reply to] Can't Post


In Reply To
Secondly I don't think qq() is required just $h{"key "} is working fine.


If you look at his code, it is required because there is a newline added to the string. qq is to quote the string, not the hash key. If you drop the newline then no quotes at all are required.
-------------------------------------------------


vikas.deep
User

May 14, 2009, 10:41 AM

Post #9 of 17 (1976 views)
Re: [alex_v2] How to populate a Hash [In reply to] Can't Post

At the end of a long-long day I am back to zero and again the same problem "How to polpulate a hash"
First my code

open (my $FH, 'parse21.txt') or die "Cannot open the file parse21.txt: $!";
open (my $FHH, '>parse211.txt') or die "Cannot open the file parse212.txt: $!";
@key = <$FH>;
chomp (@key);
my $arref = \@key;
my $gb = Bio::DB::SwissProt->new;
my $seqio = $gb -> get_Stream_by_id($arref);
while (my $clone = $seqio->next_seq )
{
print $FHH $clone ->seq,"\n";
}close $FHH;
open (my $FHHH, 'parse211.txt') or die "Cannot open the file parse211.txt: $!";
@value = <$FHHH>;
chomp (@value);
@h{@key} = @value;
print $h{'GFPL_ANEMA'};

Again the same (dreaded) output
#[root@localhost Documents]# perl bp.pl
#Use of uninitialized value in print at bp.pl line 46, <$FHHH> line 4.

Here a few classes of Bio:Perl are used which fetch some biological sequences from online databases like SWISS-PROT; None of which should matter. At the heart of the problem is a key file which has been opened using $FH and a value file which has been opened twice once for writing with a file handle $FHH and then a second time for reading using $FHHH.
Surprisingly a
print keys %h
does not prints anything while
print values %h prints what is expected and
print %h prints what is expected only for the last key and for the rest it is just printing the values!.
Also if @key is not chomped then keys ARE PRINTED!!
the parse21.txt(or $FH) file carries the keys
#GFPL_ANEMA
#A7UAL1_9CNID
#A8CLP2_MONEF
#A8CLP7_9CNID
and parse211.txt($FHH) carries the values
#MALSNKFIGDDMKMTYHMDGCVNGHYFTVKGEGNGK
#MSVIKSVMKIKLRMDGIVNGHKFMITGEGEGKPFEG
#MALSKQSLPSDMKLIYHMDGNVNGHSFVIKGEGEGK
#MSVIKTDMKIRLQMQGAVNGHPFVITGEGEGKPYEG

FrownFrownFrown
-For all my suggestions " I am sure someone else can do it in a better or elegant manner!"

(This post was edited by vikas.deep on May 14, 2009, 11:00 AM)


KevinR
Veteran


May 14, 2009, 11:58 AM

Post #10 of 17 (1971 views)
Re: [vikas.deep] How to populate a Hash [In reply to] Can't Post

Start printing the values of file reads to see what is returned.


Code
open (my $FHH, '>parse211.txt') or die "Cannot open the file parse212.txt: $!";  
@key = <$FH>;
chomp (@key);

print "\@key values\n";
print "<$_>\n" for @key;


my $arref = \@key;
my $gb = Bio::DB::SwissProt->new;
my $seqio = $gb -> get_Stream_by_id($arref);
while (my $clone = $seqio->next_seq )
{
print $FHH $clone ->seq,"\n";
}close $FHH;
open (my $FHHH, 'parse211.txt') or die "Cannot open the file parse211.txt: $!";
@value = <$FHHH>;
chomp (@value);

print "\@value values\n";
print "<$_>\n" for @value;

@h{@key} = @value;
print $h{'GFPL_ANEMA'};


The <> brackets are there so you can see if there are some empty values getting passed in the arrays. Could be blank lines in the file.

Please use the code tags to post code.
-------------------------------------------------


FishMonger
Veteran / Moderator

May 14, 2009, 12:00 PM

Post #11 of 17 (1970 views)
Re: [vikas.deep] How to populate a Hash [In reply to] Can't Post

Please use the code tags when posing your code and add some blank lines to help make it easier to read/follow.


Quote
a value file which has been opened twice once for writing with a file handle $FHH and then a second time for reading using $FHHH


Why are you doing that?

Just store that data in an array instead of the file, or populate the hash one record at a time in the while (my $clone = $seqio->next_seq ) loop.

You should make it a habit of using Data::Dumper (or similar module) to dump out your data structures so you can see where and why the data is not as expected.


FishMonger
Veteran / Moderator

May 14, 2009, 12:20 PM

Post #12 of 17 (1967 views)
Re: [vikas.deep] How to populate a Hash [In reply to] Can't Post

This will probably need a slight tweak.


Code
open (my $FH, 'parse21.txt') or die "Cannot open the file parse21.txt: $!"; 

@key = <$FH>;
close $FH;

chomp (@key);
my $arref = \@key;
my %hash;

my $gb = Bio::DB::SwissProt->new;
my $seqio = $gb->get_Stream_by_id($arref);

while (my $clone = $seqio->next_seq ) {

my $key = shift @key;

if( not $key ) {
warn "\$key is empty\n";
next;
}

$hash{ $key } = $clone;

}
print $h{'GFPL_ANEMA'} ? $h{'GFPL_ANEMA'} : "\$h{'GFPL_ANEMA'} is undefined\n";



alex_v2
User

May 14, 2009, 12:52 PM

Post #13 of 17 (1964 views)
Re: [FishMonger] How to populate a Hash [In reply to] Can't Post


In Reply To
Please use the code tags when posing your code and add some blank lines to help make it easier to read/follow.


Quote
a value file which has been opened twice once for writing with a file handle $FHH and then a second time for reading using $FHHH


Why are you doing that?

Just store that data in an array instead of the file, or populate the hash one record at a time in the while (my $clone = $seqio->next_seq ) loop.

You should make it a habit of using Data::Dumper (or similar module) to dump out your data structures so you can see where and why the data is not as expected.


As Fish stated put the line use Data::Dumper in the top of your file then warn or print the hash to see its values. This is how I caught the return characters in your other stuff last night. To print dumper just do:

print Dumper(\%h);

Getting ready to be invaded by a bunch of 5 year olds for my nieces birthday today so I don't have as much time today to go into cade and do some testing of my own. But as Fish stated Data::Dumper is your friend get to know it well.

-Alexander


vikas.deep
User

May 14, 2009, 11:05 PM

Post #14 of 17 (1957 views)
Re: [KevinR] How to populate a Hash [In reply to] Can't Post

First of all my apology for not posting the code in a proper format, even when once before FishMonger has also pointed out this very mistake. I know none but fools repeat their mistakes but as of now I am so hard pressed that I do not have time to familiarize myself with "How to use quotes to post codes?" may be this week end that is on top of my things to do. (even when Weekends are busier than week days!!)
I have tried your code and it shows that array values is working fine as expected but there is problem with array key.

#Output for @key without chomp (All the rest of the code including chomp@key has been #commented)
@key values
<GFPL_ANEMA
>
<A7UAL1_9CNID
>
<A8CLP2_MONEF
>
<A8CLP7_9CNID
>

You can see that from somewhere a newline has crept in

#Output of @key after chomp (chomp @key has been de-commented)
>GFPL_ANEMA
>A7UAL1_9CNID
>A8CLP2_MONEF
<A8CLP7_9CNID>

This time chomp has worked but It is clear that only the last key is been printed as expected and all the rest are not printing as per expectation
No doubt that
print $h{'GFPL_ANEMA'};
gives

#[root@localhost Documents]# perl bprev.pl
Use of uninitialized value in print at bprev.pl line 35, <$FHHH> line 4.

but
print $h{'A8CLP7_9CNID'};

gives perfect answer

MSVIKTDMKIRL------ASTLPSKAK[root@localhost Documents]#

Here "A8CLP7_9CNID" is the last key

Does this means we have to chomp twice the @key
-For all my suggestions " I am sure someone else can do it in a better or elegant manner!"

(This post was edited by vikas.deep on May 14, 2009, 11:07 PM)


vikas.deep
User

May 14, 2009, 11:28 PM

Post #15 of 17 (1953 views)
Re: [FishMonger] How to populate a Hash [In reply to] Can't Post

I am sorry for not properly explaining things. In my code the

next_seq

is a method which is returning an object of another class Bio::Seq

and the seq is the method that is actually returning the sequence seq should have been written as seq() to make things clearer and seq() will work only on an object for Bio::Seq class

So we can't get away without using seq()

next_seq() cannot be used to fetch sequences. It is only returning objects of Bio::Seq class.

And the next_seq somehow converts clone into an object of Bio::Seq class So that we can easily call seq() method to act upon the clone object
-For all my suggestions " I am sure someone else can do it in a better or elegant manner!"

(This post was edited by vikas.deep on May 14, 2009, 11:33 PM)


vikas.deep
User

May 15, 2009, 12:26 AM

Post #16 of 17 (1946 views)
Re: [FishMonger] How to populate a Hash [In reply to] Can't Post

In my earlier post I said that I will learn how to use quotes/codes this week end because I thought I will have to read some 10-20 pages of perl documentation for that. But I never knew that all I have to do is to try use the buttons already provided here

Following your (FishMonger) code
A data dumperon %hash is giving the following

Code
[root@localhost Documents]# perl bprev.pl 
$VAR1 = {
'A8CLP7_9CNID' => 'MSVIKTDMKIRL------PSKAK',
' => 'MALSN-------------KFIGDDMKM',
' => 'MALSKQ--------------SLPSDMKE',
' => 'MSVIKSVMK------------IKLRMDGIVNK'
};


It is clear that only one Key-Value pair has been initialized but in other cases keys are missing.
Kindly help me to get the keys for other values in this hash to populate this hash

Fearing such a problem I tried to create a "dummy/ toy-hash " yesterday itself with keys as common fruits and there colours as values; that hash was easily populated after Alex's help
butnext when I came back to work for a "true- hash again problems-------

And more to that


Code
push my @arr,  keys %hash;  
#print Dumper (\%hash)
print Dumper (\@arr);


prints

Code
[root@localhost Documents]# perl bprev.pl 
$VAR1 = [
'A8CLP7_9CNID',
', 'GFPL_ANEMA
', 'A8CLP2_MONEF
' 'A7UAL1_9CNID
];

Only the first key is in proper ' ' for all rest the key seems to be 'key\n'
and Dta::Dumper on

Code
push my @arr,  values %hash;  
#print Dumper (\%hash)
print Dumper (\@arr);


gives

Code
$VAR1 = [ 
'MSVIKTDMKIRLQ----SKAK',
'MALSNKFIGDDMKM--------PF',
'MALSKQSLPSD----CFTE',
'MSVIKSVMKIK--------------PIKAK'
];


Surely Sir Data::Dumper makes it easier to guess what is happening where but How to correct what is going wrong here are are the contents of key file


GFPL_ANEMA
A7UAL1_9CNID
A8CLP2_MONEF
A8CLP7_9CNID
-For all my suggestions " I am sure someone else can do it in a better or elegant manner!"

(This post was edited by vikas.deep on May 15, 2009, 12:58 AM)


vikas.deep
User

May 15, 2009, 3:14 AM

Post #17 of 17 (1936 views)
Re: [vikas.deep] How to populate a Hash [In reply to] Can't Post

"HOW TO POPOULATE THE HASH"
The Issue is Finally Resolved. In the keys file I do not yet understand how but there was an extra "\n".
So solution was simple I twice used the Chomp function.
Even when in another file I had used chomp @key only once and in fact using chop twice wiped away the entire array key.
THANK YOU ALL(MANY TIMES) for very enthusiastically participating in the discussion.
I learnt about Data::Dumper and

Code
print "\@value values\n";  
print "<$_>\n" for @value;

which helped me to correctly diagnose the problem.
Yes there was no need to write the values in a separate file and then again opening it with a third file handle instead

Code
$h{ $key } = $clone ->seq();

was used to finally populate the hash

Quote
ONCE A CODE RUNS SUCCESSFULLY WORLD AGAIN SEEMS TO BE BEAUTIFUL

Smile
-For all my suggestions " I am sure someone else can do it in a better or elegant manner!"

(This post was edited by vikas.deep on May 15, 2009, 3:21 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives