Re: Check Array Elements
by toolic (Bishop) on Jun 06, 2012 at 21:18 UTC
|
use warnings;
use strict;
use Acme::Tools qw(intersect);
my @FILES = ("ABC","DEF","GHI","JKL","MNO","PQR","STU");
if (intersect(\@FILES, [qw(ABC GHI MNO)]) == 3) {
print "yes\n";
}
else {
print "no\n";
}
__END__
yes
| [reply] [Watch: Dir/Any] [d/l] |
Re: Check Array Elements
by morgon (Priest) on Jun 06, 2012 at 21:26 UTC
|
Simply use a hash (and strict!):
use strict;
my @FILES=("ABC","DEF","GHI","JKL","MNO","PQR","STU");
my %have_file = map { $_ => 1 } @FILES;
if ($have_file{ABC} and $have_file{GHI} and $have_file{MNO} ) {
# do something
}
else {
# do something else
}
| [reply] [Watch: Dir/Any] [d/l] |
Re: Check Array Elements
by davido (Cardinal) on Jun 06, 2012 at 22:09 UTC
|
If it's just a one-time check, or if the array changes frequently, it's probably not all that efficient to suck the whole thing into a hash just to do three exists tests. Converting the big set to a hash is an O(n) operation, but a computationally more expensive one than the O(n) operation of grepping for the thee elements.
my %find;
@find{ qw( this that other ) } = ();
my $found = grep { exists $find{$_} && ( delete $find{$_} || 1 ); } @b
+ig_list;
print "Success!\n" if $found == 3;
This method uses a small three-element hash as the lookup list. Each time an entry is found, it is deleted from the lookup hash so that you assure that all three items are found (as opposed to the same item three times).
If the big array changes infrequently, and you will be doing more than a few lookups on it, then it makes sense to convert the big array to a hash and invert the search:
my %big_set;
@big_set{ @big_array } = ();
my @find = qw( this that other );
my $found = grep{ exists $big_set{$_} } @find;
print "Success!\n" if $found == 3;
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Check Array Elements
by ckj (Chaplain) on Jun 07, 2012 at 05:46 UTC
|
@FILES=("ABC","DEF","GHI","JKL","MNO","PQR","STU");
if ((ABC~~@FILES)&&(GHI~~@FILES)&&(MNO~~@FILES)){
do something}
else {
do something else}
| [reply] [Watch: Dir/Any] [d/l] |
Re: Check Array Elements
by kcott (Archbishop) on Jun 07, 2012 at 00:38 UTC
|
Here's a solution that allows you to change either the full (@files) or required (@need) lists of files. The order you supply the elements to either list doesn't matter: the code handles that for you. Also, filenames are likely to contain characters outside of the [A-Z] range (e.g. a.txt, b.pl, c.png, etc.): I've wrapped these in \Q...\E to avoid interference with the regex.
use strict;
use warnings;
my @files = qw{ABC DEF GHI JKL MNO PQR STU};
my @need = qw{MNO ABC GHI};
my $need_re = join q{\s.*?} => map { q{\b} . qq{\Q$_\E} . q{\b} } sort
+ @need;
if (join(q{ } => map { qq{\Q$_\E} } sort @files) =~ /$need_re/) {
print qq{OK\n};
}
else {
print qq{NOT OK\n};
}
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Check Array Elements
by NetWallah (Canon) on Jun 06, 2012 at 22:25 UTC
|
my @need=sort qw|ABC GHI MNO|;
my $flat=join "",@need;
my $re="\\b" . join( "|",@need)."\\b";
if ($flat eq join( "", sort grep{m/$re/}@FILES)){
say "Found!"
}
I hope life isn't a big joke, because I don't get it.
-SNL
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
This is wrong.
Counterexample:
@FILES = ("ABC", "ABC", "ABC");
Your grep would still report 3, event though "GHI" is missing.
And that is even without mentioning that the regex matches also enties like "XABCY". | [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] |
|