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

I was trying to compare 2 arrays by pattern matching @realassert only will match part of @pcov
foreach(@realassert){ my ($theline)=grep{/$_/} @pcov; push (@thelist, "$theline"); }
this is the code that i use, but it is not working. Any ideas? Thankx @pcov
yphs.pc0.samelogic.fois_ebs.sbetrgt_inst
@realassert
sbetrgt_inst
what i wan is yphs.pc0.samelogic.fois_ebs.sbetrgt_inst when @realassert matches @pcv.

Replies are listed 'Best First'.
Re: Comparing 1 array that matches in 2nd array
by frozenwithjoy (Priest) on Jul 13, 2012 at 08:20 UTC
    Your problem is that the $_ in grep{/$_/} @pcov isn't what you think it is. You want it to be referring to your regex from @realassert, but as you have it written, it is an element of @pcov.

    Also, the way you have it written results in empty elements in your final array (or undef if you remove the quotes from around $theline). Take a look at this approach:

    #!/usr/bin/env perl use strict; use warnings; use Data::Printer; my @pcov = qw( junk yphs.pc0.samelogic.fois_ebs.sbetrgt_inst nothing ) +; my @realassert = qw( stuff sbetrgt_inst other); my @thelist; foreach my $regex ( @realassert ) { push @thelist, grep{ /$regex/ } @pcov; } p @thelist;
Re: Comparing 1 array that matches in 2nd array
by davido (Cardinal) on Jul 13, 2012 at 08:23 UTC

    Kudos to frozenwithjoy for spotting the $_ collision!

    A few other things, the '.' (dot) is a special character inside of regular expressions. You probably need to wrap your match in \Q and \E. Additionally, no matter how many times your grep matches, $theline, being a simple scalar variable, will only hold ONE element from the list that grep returns. It's also not necessary to wrap $theline in quotes. Why interpolate when all you want to do is push a simple scalar variable onto an array.

    Is it possible that $theline is supposed to be @theline, so that you capture the entire list returned by grep, and push it all onto @thelist on each iteration? Capturing the return value of grep, in list context, but storing it in a scalar seems to me to be a big red flag.

    Updated to acknowledge frozenwithjoy's nice catch.


    Dave

Re: Comparing 1 array that matches in 2nd array
by brx (Pilgrim) on Jul 13, 2012 at 08:49 UTC

    The two ways I understand your question:

    First, you want to known what elements from @pcov match with at least one pattern from @realassert.

    Second, you want to know what elements from @pcov match with all patterns from @realassert

    my @pcov = ('foobar','bilbao','bobo'); my @realassert = map {quotemeta} ('foo','ba'); my $re_one = join '|',@realassert; #print $re_one; my @result_one = grep { /$re_one/ } @pcov; print "one: @result_one\n"; my @result_all = grep { my $item = $_; ! grep { $item !~ /$_/ } @realassert; } @pcov; print "all: @result_all\n"; __END__ one: foobar bilbao all: foobar

    edit: You could also look at http://perldoc.perl.org/perlop.html#Smartmatch-Operator

    edit2: typo

Re: Comparing 1 array that matches in 2nd array
by locked_user sundialsvc4 (Abbot) on Jul 13, 2012 at 16:20 UTC

    You could also just use two nested-loops, and, absent any extraordinary provocations to do otherwise, this is probably what I would do.   Something like:   (meant only to sketch the idea)

    foreach my $a (@realassert) { foreach my $b (@pcov) { if ($a =~ $b) { push @result, $b; last; // BAIL OUT OF INNERMOST LOOP .. CAN ALSO USE A LABEL } }

    There is nothing cryptic or hard-to-understand about logic that has been “unrolled” in this way, and I suppose that this is really my point.   It does the job and it is also obvious what it does, and also how to change what it does.   You don’t have to monkey-around with grep in this-or-that context, in hope of a few sub-milliseconds of completion time, if you’re just going to wind up spending more time getting the damm thing to actually work :-) than you would ever have saved by doing something so “clever.”   Furthermore, if the tests that you need to do in that innermost-loop ever become more complicated ... as they may well do ... then you can easily and confidently change it.   “Golf” games are fun to watch, but not so fun to be a participant.