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

Hi monks, I have a code that reads like this:

my %csahash; my $line=<>; while($line=<>){ if($line=~ /\b(\d\w{3})\b/){ $csahash{$1}++; } }

and the ouput is this:

2buf= 48 1lsj= 6 2bp7= 12 1ye6= 36 8icc= 1 1a2n= 4 1lz6= 2 1pw1= 5 1e4d= 4 2f8j= 28 1iw8= 24 1qbd= 2 1kf4= 7 1z53= 3 1gxx= 2 1dd6= 10 1ke5= 10 2og7= 1

I have a very similar %hash like this:

%cathhash; my $line2=<>; while($line2=<>){ if($line2=~/\b(\d\w{3})\b/){ $cathhash{$line2}++; } }

which will print out very similar output. My question is to see which of those id nos match between the hashs and give me a print out of the matches preferabaly. Thanks. A.

Ok many thanks for both ur tips. My code now looks like this :

my %csahash; my $line=<>; while($line=<>){ if($line=~ /\b(\d\w{3})\b/){ $csahash{$1}++; } } %cathhash; my $line2=<>; while($line2=<>){ if($line2=~/\b(\d\w{3})\b/){ $cathhash{$line2}++; } } foreach my $key(keys %csahash){ if(defined $cathhash{$key}){ print "$key matches. It's values are $csahash{$key} and $cathhash{$key +}\n"; } }

but when I try to execute it on the command prompt like this :

perl pl.pl csa.txt cath.txt I get nothing just a blank cursor. do I have to do something with cntrl+D? I am bit new to perl so am having teething problems. Many thanks. Ok, thanks again but when I run this code through I still get no print out, can someone tell me where I'm going wrong in my execution?

Replies are listed 'Best First'.
Re: hash question
by moritz (Cardinal) on Dec 11, 2007 at 10:46 UTC
    Are you looking for hash keys that appear in only one hash? Then look at perlfaq4, "How can I get the unique keys from two hashes?"

    Or do you want to get those keys that appear in both hashes? Then iterate over the keys of the first hash and check if they are present in the second one.

Re: hash question
by cdarke (Prior) on Dec 11, 2007 at 12:50 UTC
    With regards to your I get nothing just a blank cursor question: The first
    my $line=<>;
    reads the first line of the first file. Then the loop
    while($line=<>){ ... }
    reads ALL the remaining lines in the files. By the time it gets to
    my $line2=<>;it has exhausted the files, and it reads from stadard-input. <CTRL>D passes end-of-file to standard-input (by default) but that is probably not what you want. If you want each loop to be read for each file then it is probably easier to explicitly open the files instead. You could instead detect when the first file is closed and the second one opened using $ARGV, but that would be messy.
Re: hash question
by olus (Curate) on Dec 11, 2007 at 11:50 UTC
    One solution is going through all the keys of one the hashes and check if those are defined on the second one.
    foreach my $key (keys %csahash) { if(defined $cathhash{$key}) { print "$key matches. It's values are $csahash{$key} and $cathh +ash{$key}\n"; } }

    update
    having written a foreach, thought it would be a good candidate for a 'map' solution.
    map { print "$_ matches. It's values are $csahash{$_} and $cathhash{$_ +}\n" if(defined $cathhash{$_}) } keys %csahash;
    update 2
    updated the map solution by adding, the mistakingly droped, 'defined' to the if clause.
    Thanks johngg for pointing that out.
      Re. your map solution, I think it might be safer to test for the existence of a key in case the value is 0 or the empty string. Also grep could come into play.

      print map { qq{$_ matches. It's values are $csahash{$_} and $cathhash{$_ +}\n} } grep { exists $cathhash{$_} } keys %csahash;

      I hope this is of interest.

      Cheers,

      JohnGG