Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

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

by imrags (Monk)
doesn't seem to work NODE.owner = 700029 N.title = monktitlebar sitedoclet N.owner = 17342 -->
on Jun 10, 2009 at 07:01 UTC ( [id://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; } } }
Raghu

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 (Saint) 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

    Prints:

    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.
    Update:
    This did it:
    seek(FILE,SEEK_SET,0);
    Raghu

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

      untested:

      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?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (2)
As of 2024-04-26 02:50 GMT
Sections?
doesn't seem to work NODE.owner = 700029 N.title = Sections sitedoclet N.owner = 17342 -->
Information?
doesn't seem to work NODE.owner = 700029 N.title = Information sitedoclet N.owner = 17342 -->
Find Nodes?
doesn't seem to work NODE.owner = 700029 N.title = Find Nodes sitedoclet N.owner = 17342 -->
Leftovers?
    doesn't seem to work NODE.owner = 700029 N.title = Leftovers sitedoclet N.owner = 17342 -->
    Voting Booth?

    No recent polls found