Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Foreach loop explanation

by ananassa (Initiate)
on Nov 23, 2012 at 20:26 UTC ( #1005315=perlquestion: print w/ replies, xml ) Need Help??
ananassa has asked for the wisdom of the Perl Monks concerning the following question:

Good evening/morning everyone! I have a easy code in pearl that look through two arrays and print out the lines that match between the two array. I am using two foreach loops and I am wondering why is my output repeated as many times as the lines of one of my two files. what kind of loop would you suggest? Thanks! Here below is the code

#!/usr/bin/perl -w use strict; open (INA, $ARGV[0])|| die "unable to open file"; open (INB, $ARGV[1])|| die "unable to open file"; my $item; my $line; my @indirizzi = <INB>; my @nomi = <INA>; chomp @nomi; foreach $item(@nomi) { foreach my $line (@indirizzi){ if ($line =~ m/^$item/){ print $line; } } }

Comment on Foreach loop explanation
Download Code
Re: Foreach loop explanation
by SuicideJunkie (Priest) on Nov 23, 2012 at 21:30 UTC

    Start with a small sample of data

    Also, at line 16, try doing a print "I am now searching using '$item'\n";

    If there are blank lines in your @nomi file, you'll get the entire @indirizzi file printed out, because every line in the file will match /^/;

    One other note is that you are declaring $line and $item inconsistently. The first $line is never used, since there is a new $line declared for the inner loop.

Re: Foreach loop explanation
by Don Coyote (Monk) on Nov 23, 2012 at 21:57 UTC

    Hello. The reason is because all the lines match from one file to all the other lines in the other file.

    If I run your code on two files where some of the lines match and some do not, only the lines that match are printed.

    file1 one two three four five six seven eight file2 five six seven eight nine ten eleven twelve prints five six seven eight

    update: oh. I didnt think of that SuicideJunkie! if i add a new line between 'three' and 'four' in file one, all the lines are printed out.

Re: Foreach loop explanation
by eyepopslikeamosquito (Canon) on Nov 24, 2012 at 00:11 UTC

    Using a regex does not seem appropriate here because the lines may contain regex metacharacters. The sample code below assumes you want exact matches. You may need to tailor it for things like white space, case sensitivity, and so on.

    use strict; use warnings; @ARGV == 2 or die "usage: $0 file1 file2\n"; my $file1 = shift; my $file2 = shift; open my $in1, '<', $file1 or die "unable to open '$file1': $!"; open my $in2, '<', $file2 or die "unable to open '$file2': $!"; chomp( my @nomi = <$in1> ); chomp( my @indirizzi = <$in2> ); close $in1; close $in2; # Remove any blank or empty lines (optional, depends on your data file +s). @nomi = grep { !/^\s*$/ } @nomi; @indirizzi = grep { !/^\s*$/ } @indirizzi; # Create a hash of lines in @nomi. my %in_nomi; foreach my $item (@nomi) { $in_nomi{$item}++ } # Check if each line in @indirizzi is in nomi. # Note: does not check for duplicate lines in @indirizzi. foreach my $line (@indirizzi) { print "$line\n" if $in_nomi{$line}; }

    See perlfaq4, especially the frequently asked questions:

    • How can I remove duplicate elements from a list or array?
    • How can I tell whether a certain element is contained in a list or array?
    • How do I compute the difference of two arrays?
    • How do I compute the intersection of two arrays?

Re: Foreach loop explanation
by Kenosis (Priest) on Nov 24, 2012 at 01:54 UTC

    In case you may be interested, List::Compare provides a means of getting the intersection of two lists. In addition to it being well designed, it will only return a list of unique elements--in case either list has repeating elements.

    For example, modify Don Coyote's data to the following:

    file1 ----- one two three four five six seven eight file2 ----- five five five six seven eight nine ten eleven twelve

    And run the following on it:

    #!/usr/bin/perl -w use strict; use warnings; use List::Compare; @ARGV == 2 or die 'Error: Two files needed for comparison.'; open my $inA, '<', $ARGV[0] or die qq{Unable to open file "$ARGV[0]": +$!}; chomp( my @nomi = <$inA> ); close $inA; open my $inB, '<', $ARGV[1] or die qq{Unable to open file "$ARGV[1]": +$!}; chomp( my @indirizzi = <$inB> ); close $inB; my $lc = List::Compare->new(\@nomi, \@indirizzi); my @intersection = $lc->get_intersection; print "$_\n" for @intersection;

    Here's the output:

    eight five seven six

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (2)
As of 2014-09-22 01:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (176 votes), past polls