Syntactic Confectionery Delight PerlMonks

### Compare all array values without a loop

 on Oct 19, 2004 at 14:15 UTC Need Help??

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

if I have
\$foobar='D';
@array=('A', 'B', 'C', 'D');

is there a way I can compare \$foobar to every @array value in a single if statement? without a loop?

for example...

I dont think that works, but it might help describe what Im saying better... thanks

Replies are listed 'Best First'.
Re: Compare all array values without a loop
by edan (Curate) on Oct 19, 2004 at 14:19 UTC
if ( grep { \$_ eq \$foobar} @array ) { }

Update: Use the above code if you really want to compare all array values (which is what you said). If you really want to just know if the value is in the array (and then stop searching), you might try the following, which might perform better in certain situations:

use List::Util qw(first); if ( first { \$_ eq \$foobar } @array ) { }
--
edan

I believe the original poster wanted to know whether every value in the array equalled the given value, not whether it occurred once. Perhaps he could clarify. (Of course, now both answers are available in replies.)
rjbs

I think it's not very clear from the original post, but my assumption was that the poster was looking to solve the "is this value in this list" problem, so that's what I solved. I think this is a far more common problem than "is this list composed exclusively of this value"... don't you?

--
edan

Assuming that \$foobar isn't undefined you should have a definedness check for the return value of first too. \$foobar may be 0 or "".

If undef is allowed as comparision value, use

defined( defined \$foobar ? first { \$_ eq \$foobar } @array : first { not defined \$array[\$_] } 0 .. \$#array )

ihb

See perltoc if you don't know which perldoc to read!

Quantum::Superpositions has any() and all() operations that may fit the bill. I don't know how the performance compares to List::Util and don't have time to check. Its just a fun module.
yay, thank you!
Re: Compare all array values without a loop
by dragonchild (Archbishop) on Oct 19, 2004 at 14:25 UTC
use Quantum::Superpositions; my \$foobar = 'D'; my @array = 'A' .. 'D'; if (\$foobar eq any( @array ) ) { print "Yay!\n"; } else { print "Boo\n"; }

In Perl6, the any and all functions will be keywords.

Being right, does not endow the right to be rude; politeness costs nothing.
Being unknowing, is not the same as being stupid.
Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Re: Compare all array values without a loop
by fergal (Chaplain) on Oct 19, 2004 at 14:28 UTC
If you're basically looking for a quick Set membership test then using a hash rather than an array coould help.
my %hash = ('a' => undef, 'b' => undef, 'c' => undef, 'd' => undef); if (exists \$hash{'a'}) { # yadda yadda }
Setting up the hash can be made a bit neater once you know what a hash slice is
my %hash; @hash{'a', 'b', 'c', 'd'} = ();
If your set of elements is going to be large and you're going to be checking frequently then a hash will be much quicker than anything that searches an array. Inserting and removing elements is also quick and doesn't have a problem with duplicates like an array could.

You could also do a cpan search for "set" and use one of the modules there, some of them would be even faster and than hashes I think.

Re: Compare all array values without a loop
by rjbs (Pilgrim) on Oct 19, 2004 at 14:22 UTC
if (grep({ \$_ eq \$foobar } @array) == @array) { ... }
"If the number of elements equal to \$foobar is the same as the number of elements in the array..." or
unless (grep { \$_ ne \$foobar} @array) { ... }
"Unless you find an element that is not equal to foobar..."

Of course, these are both loops of a kind.
rjbs
Re: Compare all array values without a loop
by radiantmatrix (Parson) on Oct 19, 2004 at 14:35 UTC

You could join the array into a scalar with an unusual character as a separator, then use a match.

\$foobar='D'; \$sep = chr(1); @array = ('A','B','C','D'); if ((\$sep.join(\$sep,@array).\$sep) =~ m/\$sep\$foobar\$sep/) { print "Found a \$foobar in \@array!"; }

The \$sep on either side of the join() ensures that any potential match will begin and end with chr(1). You can pick other separator characters, as long as you can be sure they will not exist in your array (chr(1) is a pretty unlikely thing to find).

Of course, it would be better to use hash-keys if you can...

\$foobar='D'; %hash = ( 'A' => undef, 'B' => undef, 'C' => undef, 'D' => undef ); print "Found a \$foobar in \%hash" if exists \$hash{\$foobar};

If you're avoiding multiple loop passes for performance, then you could use a one-time loop to convert the array to a hash:

@array = ('A','B','C','D'); for (@array) { \$hash{\$_} = undef; } #now we have the same hash as in the previous example. #so, you can do this repeatedly with out a hit: \$foo = 'D'; if (exists \$hash{\$foo}) { print "There was a \$foo in the array\n"; }
require General::Disclaimer;
"Users are evil. All users are evil. Do not trust them. Perl specifically offers the -T switch because it knows users are evil." - japhy

@array = ('A','B','C','D'); for (@array) { \$hash{\$_} = undef; }
you can use
my @array = qw/A B C D/; my %hash; @hash{@array} = ();

Re: Compare all array values without a loop
by si_lence (Deacon) on Oct 19, 2004 at 14:25 UTC
Hi,
You can use grep for it.
This uses an implicit loop, but it is quite close to
the syntax you suggest:
my \$foobar='D'; my @array=('A', 'B', 'C', 'D'); if ( grep {\$_ eq \$foobar } @array ) { #yadda yadda };

si_lence
Re: Compare all array values without a loop
by Random_Walk (Prior) on Oct 19, 2004 at 15:54 UTC

Just for fun here is an evil eval way to do it without a loop.

@a=('A', 'B', 'C', 'D'); \$b='D'; if (eval "if(\\$b eq \"".(join"\"){return 1}if(\\$b eq \"",@a)."\"){retu +rn 1}") { Print "It was there\n" }

Cheers,
R.

Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://400532]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2023-02-07 04:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?