Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

Hash/file --> doesn't seem to work

by imrags (Monk)
on Jun 10, 2009 at 07:01 UTC ( #770215=perlquestion: print w/ replies, xml ) Need Help??
imrags has asked for the wisdom of the Perl Monks concerning the following question:

I've written this code, it's supposed to traverse the file
the same number of times as the size of the hash, however,
does only happen once, where is the mistake?
while(my ($key,$value)= each (%hash_table)) { while(<FILE>) { chomp; my ($objid,$other) = split(/\s+/,$_); if($objid =~ /$key/i) { print "$key is present in $objid\n"; } else { next; } } }

Comment on Hash/file --> doesn't seem to work
Download Code
Replies are listed 'Best First'.
Re: Hash/file --> doesn't seem to work
by fullermd (Priest) on Jun 10, 2009 at 07:08 UTC

    After the first time through, you're at the end of FILE, so the while() is never entered (i.e., it gets EOF right off). Try using seek.

    However, it will probably more efficient (if the file is rather small relative to available memory anyway) to load in the data and then iterate over it pre-parsed, than to re-parse the file and each line every time.

      At first time, when inner loop execution is over the file pointer will be in EOF. so in next time of checking While(<FILE>) this condition will get false. so it wont go inside inner while loop.

      you can do any one of the following :
      1. Before inner loop begins you can open file handle and at the end of inner while loop close the file handle.
      2.In the beginning of the inner while loop you can make the file pointer to point to the beginning of file using 'seek'. perldoc -f seek.

Re: Hash/file --> doesn't seem to work
by GrandFather (Sage) on Jun 10, 2009 at 10:25 UTC

    Probably you would be better to construct a regular expression using Regexp::Assemble from the hash keys and perform a single pass through the file. Consider:

    use strict; use warnings; use Regexp::Assemble; my %hash_table = (12345 => 1, 8976 => 2, 1046 => 3); my $assemble = Regexp::Assemble->new (flags => 'i'); $assemble->add (keys %hash_table); my $match = $assemble->re (); while (<DATA>) { chomp; my ($objid, $other) = split; if ($objid =~ /($match)/) { print "$1 is present in $objid\n"; } } __DATA__ 012345998 line matches 000104600 line matches 012389710 line doesn't match


    12345 is present in 012345998 1046 is present in 000104600

    True laziness is hard work
Re: Hash/file --> doesn't seem to work
by Anonymous Monk on Jun 10, 2009 at 07:39 UTC
    If your file is small go with the advice of reading it into memory as given above.

    If that is unpractical read one line and iterate over the hash for each line. I.e. switch the two loops. This can be costly as well if the hash is big.

Re: Hash/file --> doesn't seem to work
by imrags (Monk) on Jun 10, 2009 at 09:12 UTC
    Well, in my case, the file is big and the hash is relatively small...
    hence i chose it this way. Is there a better way to do it?
    I'm sure there must be, but just that i don't know them :(
    I'll try to use seek and get to the beginning of the file
    and then post the complete code.
    This did it:

      But this way vou have to read the big file often. As supposed above it would be better, to switch the while loops.


      while(<FILE>) { chomp; my ($objid,$other) = split(/\s+/,$_); while(my ($key,$value)= each (%hash_table)) { if($objid =~ /$key/i) { print "$key is present in $objid\n"; } else { next; } } }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://770215]
Approved by planetscape
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (8)
As of 2015-11-25 23:32 GMT
Find Nodes?
    Voting Booth?

    What would be the most significant thing to happen if a rope (or wire) tied the Earth and the Moon together?

    Results (693 votes), past polls