Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

Grep inside the while Loop

by snape (Pilgrim)
on Oct 20, 2010 at 22:49 UTC ( #866426=perlquestion: print w/ replies, xml ) Need Help??
snape has asked for the wisdom of the Perl Monks concerning the following question:

It is more of a conceptual question rather than a logic question. I have 2 while loops in my program below. The first while loop is used to store the set of words in an array after opening the first file. The second while loop is used to find if there is a match between the the words in the array with the words in the the 3rd column of second file.

I used grep inside the while loop for checking the "matched text". My code is as follows:

my @list_match; my @matchArray; open IN, "Data.txt" or die $!; # The file here has one column while(<IN>){ chomp($_); push @list_match, $_; } close(IN); open INPUT, "Data_Large.txt" or die $!; # It is a tab delimited file having 7 columns. I am looking # to match + the 3rd column words with the above # @list_match array while(<INPUT>){ chomp($_); my @arrList = split('\t', $_); print "Found $arrList[2]", if (grep {$_ eq $arrList[2]} @list_match) +## assuming it is a character } close(INPUT);

Now if I use the above code then it doesn't find the "match word". I think it is assuming "$_" as the entire current line of the file. My question is why doesn't it assume as the current index of the array @list_match. If you use the same convention of grep in comparing the 2 arrays then it will work. For example:

for (my $i = 0; $i <= 10; $i++){ print "Found $arrList[$i]" if (grep {$_ eq $arrList[$i]} @list_match) + ## assuming that @arrList is an array of column 3 elements }

I know there is another way of using grep like

grep {/$arrList[2]/} @list_match ## if I am searching for $arrList[2] +

but I would like to know why the prior grep syntax in the while loop doesn't work. Thanks a lot.

UPDATE : I am sorry, my code is correct and there is no collision of $_. The above code works. I did a mistake while I was coding before. Sorry for the inconvenience. Thanks

Replies are listed 'Best First'.
Re: Grep inside the while Loop
by morgon (Deacon) on Oct 20, 2010 at 23:08 UTC
    I think it is assuming "$_" as the entire current line of the file.
    No. At least in recent Perls (I am using 5.12) the $_ used in grep is localized and contains in your example the current element of the array - your code is ok here.

    You can easily verify that yourself if you add a trace, e.g:

    ... grep {print STDERR "\$_: $_\n"; $_ eq $arrList[2]} @list_match
    So whatever the problem is, it is not a collision of $_.

    btw: I would use a variable when looping through a file, instead of using $_:

    while(my $line = <INPUT>){ chomp($line); ...
    Then you don't have to worry about $_ getting clobbered by something else and you code becomes more readable.

      Yeah you are right. I made a programming mistake due to which my grep commend was not working. It was not a questions of $_ collision. Thanks for the enlightening me.

Re: Grep inside the while Loop (any)
by toolic (Bishop) on Oct 21, 2010 at 00:57 UTC
    Apparently, you have solved your problem. I'd like to point out that you could use the any function from the CPAN List::MoreUtils module as an alternative to the grep built-in function. One advantage is that any will stop searching through your array as soon as it finds a match, whereas grep will always search through the entire array. Therefore, any has the potential of being faster.

    Another advantage (in my opinion) is that it makes the code slightly more readable, as do some other CPAN modules, such as File::Slurp and autodie (now a core pragma as of perl 5.10). Consider the following re-write of your code (UNTESTED since you did not provide input data):

    use strict; use warnings; use autodie; use File::Slurp qw(slurp); use List::MoreUtils qw(any); my @list_match = slurp('Data.txt'); chomp @list_match; open my $fh, '<', 'Data_Large.txt'; while (<$fh>) { my $item = (split)[2]; print "Found $item\n" if any {$item eq $_} @list_match; } close $fh;

    Or, better yet... use a hash.

      Thanks toolic

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (4)
As of 2016-08-27 22:33 GMT
Find Nodes?
    Voting Booth?
    The best thing I ever won in a lottery was:

    Results (389 votes). Check out past polls.