Re: using grep to match more than two words
by McDarren (Abbot) on Jun 12, 2007 at 06:37 UTC
|
Firstly, @arr1 = ("Sun" "Moon" "Venus" "Pluto" "Neptune"); is wrong, and will throw an error if you try use it. Your either need to do:
@arr1 = qw(Sun Moon Venus Pluto Neptune);
or..
@arr1 = ("Sun", "Moon", "Venus", "Pluto", "Neptune");
Secondly, to answer your question - here is one way to do it:
if ((grep {$_ eq 'Sun'} @arr1) && (grep {$_ eq 'Moon'} @arr1)) {
print "We have both a sun and a moon - yay!\n";
}
else {
print "Something is missing...\n";
}
--Darren | [reply] [d/l] [select] |
Re: using grep to match more than two words
by blazar (Canon) on Jun 12, 2007 at 08:51 UTC
|
Now I need to find out with the help of grep if the array
[snip]
I am actually looking for the above queries solution in single statement.
A few considerations:
- please stop friggin' putting your posts in pre tags: they're discoraged at the Monastery and certainly not useful here to present some simple text;
- nobody seems to have noticed yet, but why do you insist that you "need" to use grep and that you want a single statement? This strongly smells like homework!
- Thanks to stuff like do, quite about anything in Perl can be a "single statement".
To illustrate the last point, the following does use grep and is a single statement:
print "ok\n" if 2 == grep sub {
my $x=shift;
$_ eq $x and return 1 for @arr1;
0;
}->($_), qw/Sun Moon/;
| [reply] [d/l] [select] |
Re: using grep to match more than two words
by naikonta (Curate) on Jun 12, 2007 at 07:12 UTC
|
Well, I feel bit ithcyitchy, so here's a one (probably generic) way to do it.
use strict;
use warnings;
my @source = qw(Sun Moon Pluto Venus Neptune);
my @target = @ARGV ? @ARGV : qw(Sun Moon);
print is_target_in_source(\@target, \@source), "\n";
sub is_target_in_source {
my($target, $source) = @_; # omits arg validation
my %target = map { $_ => 1 } @$target;
my $in = 0;
$target{$_} && $in++ for @$source;
return $in == @$target ? 'Yes' : 'No';
}
One can also play with one or more functions in List::MoreUtils.
But I found Array::Utils simpler to use:
use strict;
use warnings;
use Array::Utils 'intersect';
my @source = qw(Sun Moon Pluto Venus Neptune);
my @target = @ARGV ? @ARGV : qw(Sun Moon);
my @in = intersect @target, @source;
print @in == @target ? 'Yes' : 'No';
Update: See also this FAQ entry
Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!
| [reply] [d/l] [select] |
Re: using grep to match more than two words
by johngg (Canon) on Jun 12, 2007 at 09:23 UTC
|
Another way to do it would be to use regex look-aheads in alternation (Sun followed by Moon or Moon followed bu Sun) and do a match against the array interpolated into a string.
use strict;
use warnings;
my @arrays = (
[ qw{Sun Moon Venus Pluto Neptune} ],
[ qw{Jupiter Mercury Moon Io} ],
[ qw{Europa Moon Ganymede Sun Earth} ],
[ qw{Venus Sun Saturn Titan} ],
);
my $rxSunAndMoon = qr
{(?x)
(?:\bSun\b(?=.*\bMoon\b))
|
(?:\bMoon\b(?=.*\bSun\b))
};
foreach my $raRocks ( @arrays )
{
print qq{Array: @$raRocks\n};
print
qq{@$raRocks} =~ $rxSunAndMoon
? qq{ Found Sun and Moon\n}
: qq{ No match\n};
}
The output is
Array: Sun Moon Venus Pluto Neptune
Found Sun and Moon
Array: Jupiter Mercury Moon Io
No match
Array: Europa Moon Ganymede Sun Earth
Found Sun and Moon
Array: Venus Sun Saturn Titan
No match
I hope this is of interest. Cheers, JohnGG | [reply] [d/l] [select] |
Re: using grep to match more than two words
by dewey (Pilgrim) on Jun 12, 2007 at 06:24 UTC
|
+
#!/usr/bin/perl
+
+
use strict;
use warnings;
my @arr1 = qw(Sun Moon Venus Pluto Neptune);
my @arr2 = qw(Son Moon Venus Pluto Neptune);
print "\@arr1 has both"
if grep {/^Sun$/} @arr1
and grep {/^Moon$/} @arr1;
print "\@arr2 has both"
if grep {/^Sun$/} @arr2
and grep {/^Moon$/} @arr2;
But after some consideration, I feel better about this slightly different phrasing:
print "\@arr1 has both"
if grep {$_ eq "Sun"} @arr1
and grep {$_ eq "Moon"} @arr1;
I don't know if I should really be concerned about the regular expression's interpretation of $, but in any case since we seem to want exact equality we might as well write eq. I've opted not to use the EXPR, LIST form of grep to avoid awkward parentheses, but there might be a better way around that :)
| [reply] [d/l] [select] |
Re: using grep to match more than two words
by Samy_rio (Vicar) on Jun 12, 2007 at 06:25 UTC
|
use strict;
use warnings;
my @arr1 = ("Sun", "Moon", "Venus", "Pluto", "Neptune");
((grep/^(Sun|Moon)$/, @arr1) == 2) ? (print "True") : (print "False");
Anyway first look into these links How do I post a question effectively? & How (Not) To Ask A Question
Regards, Velusamy R. eval"print uc\"\\c$_\""for split'','j)@,/6%@0%2,`e@3!-9v2)/@|6%,53!-9@2~j';
| [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
|
| [reply] |
Re: using grep to match more than two words
by pgor (Beadle) on Jun 12, 2007 at 15:54 UTC
|
My solution is almost like naikonta's, except I'm removing from the list of required entries instead of just counting matches. This allows you to terminate early once you've found everything required.
sub containsAll {
my ($arrEverything, $arrRequire) = @_;
my %stillRequired = map { $_ => 1 } @$arrRequire;
for my $entry ( @$arrEverything ) {
if ( delete($stillRequired{$entry}) ) {
last unless %stillRequired;
}
}
return %stillRequired ? 0 : 1;
}
Call as containsAll(\@arr1,['Sun','Moon'])
Feel free to take the concept and make it into your single statement requirement, since I don't see how anything maintainable can come of that kind of requirement.
pg
| [reply] [d/l] [select] |
Re: using grep to match more than two words
by johngg (Canon) on Jun 12, 2007 at 22:02 UTC
|
A subroutine inspired by the responses from naikonta and pgor but greping using exists against an on-the-fly hash constructed from the elements of @$raAll.
sub isTargetInAll
{
my ($raAll, $raTarget) = @_;
return
@$raTarget
==
grep
{
exists { map { $_ => 1 } @$raAll }->{$_}
}
@$raTarget;
}
I think that should be reliable as long as @$raTarget doesn't contain duplicates; if you were looking for a Sun and two Moons you would get a false positive if @$raAll had a Sun and just one Moon.
Cheers, JohnGG | [reply] [d/l] [select] |