1

I have an array with two values and need to perform some operations if input is not in that array.

I tried like

if ($a ne ('value1' || 'value2')

if (($a ne 'value1' ) || ($a ne 'value2' ))

Both methods didn't work. Can anyone please help?

1

7 Answers 7

7

You could use the none function from List::MoreUtils.

If you really have an array as your subject line says then your code would look like this

use List::MoreUtils 'none';

if ( none { $_ eq $a } @array ) {
  # Do stuff
}

or if you really have two constants then you could use this

if ( none { $_ eq $a } 'value1', 'value2' ) {
  # Do stuff
}

but in this case I would prefer to see just

if ( $a ne 'value1' and $a ne 'value2' ) {
  # Do stuff
}
Sign up to request clarification or add additional context in comments.

4 Comments

++ I had never thought of this way but Smart::Match operates like a "Util" module. It also has a none function where you would do: if ( $x ~~ none (@array) ) {say "not here so do stuff"}. It is almost as if it were acting like a Match::Util enhancement for a future (much simplified) version of the ~~ operator. Adding Smart::Match as a response.
@G.Cito: I like to give smart matching, or anything related to it, a very wide berth, and I dread having to write any quantity of code using the Perl 6 version. The problem is that it tries to be a DWIM operator and it's impossible to remember what it does with any given combination of parameters. I'd much sooner say what I mean and get the right result, as well as have others understand my code
I can see how it may possibly be so "smart" that it will be difficult to simplify. Simplifying something can be complex, but it is taking a long while to get it right.
@G.Cito: In general, the smart match operator performs one of the functions available in List::MoreUtils. If you add to that the dereferencing of references then you pretty much have it covered, and each different operation has a different name as well, so you're not writing $thing1 MAGIC $thing2 everywhere. Even object-oriented code can be problematic with such things, and that is about as far as I want to go
5

$a is not in the array if it's different to the first element and it's different to the second one, too.

if ($x ne 'value1' and $x ne 'value2') {

For a real array of any size:

if (not grep $_ eq $x, @array) {

(I use $x instead of $a, as $a is special - see perlvar.)

5 Comments

reserve and for flow control; use && in expressions
@VadimPushtaev That is certainly valid when you're checking if something is in an array, but in this case, we're checking if something is not in an array, which necessarily requires iterating through every single element. You could use grep or List::MoreUtils::none, pick your poison.
@ThisSuitIsBlackNot, no, that's wrong. none doesn't necessarily iterate through every single element, it stops after the first match, just like any.
@VadimPushtaev Ah, you're right. You only have to iterate through every element if there are no matches.
4
if ($a ne ('value1' || 'value2')

evaluates to

if ($a ne 'value1')

and

if (($a ne 'value1' ) || ($a ne 'value2' ))

is always TRUE.

You might try

if ($a ne 'value1' and $a ne 'value2')

or

if (!grep{$a eq $_} 'value1', 'value2')

2 Comments

@VadimPushtaev: I think should avoid is overstating it. This is simply one of the edicts of Perl Best Practices, and the reason is that grep compares all elements of the list, regardless of whether an earlier match could short-circuit the process. As long as this is borne in mind, grep is a fine way of doing this, especially since the list is only two items in length, and the extra computing would be insignificant in any code that also reads data from a disk file
1

Building on the smartmatch solution by @Dilbertino (nice nick) using match::simple by @tobyink to ease the pain of smartmatch going away (I miss it already):

use match::simple;
my @array = qw(abcd.txt abcdeff.txt abcdweff.txt abcdefrgt.txt);
my $x="abcd.txt" ;
say "it's there" if ($x |M| \@array );

The |M| operator from match::simple can be replaced with a match function which speeds things up a bit (it is implemented with XS):

use match::simple qw(match);
my @array = qw(abcd.txt abcdeff.txt abcdweff.txt abcdefrgt.txt);
my $x="xyz.txt" ;

if ( match ( $x, \@array ) ) {
     say "it's there!" ;
}
else {
     say "no hay nada";
} 

It's "simple" because the RHS controls the behavior. With match::simple if you are matching against an array on the RHS it should be an arrayref.

Smart::Match also has a none function. To use it you would do:

if ( $x ~~ none (@array) ) { 
   say "not here so do stuff ..."; 
}

Appendix

Discussion here on Stackoverlfow (see: Perl 5.20 and the fate of smart matching and given-when?) and elsewhere (c.f. the Perlmonks article by @ikegami from circa perl-5.18) gives the context for the smartmatch experiment. TLDR; things might change in the future but meanwhile, you can go back in time and use match::smart qw(match); with perl-5.8.9 proving once again that perl never dies; it just returns to its ecosystem.

In the future something like Smart::Match (i.e. the non-core CPAN module not the concept) can help supercharge a simplified smart matching operator with helper functions that read like adverbs and adjectives and have the added bonus (as I understand it) of clarifying/simplifying things for perl itself since the ~~ operator will have a less ambiguous context for its operations.

1 Comment

The topic hasn't come up again on p5p since those posts of mine. Someone interested needs to step up
1

I would do something like this using grep with a regex match

#!/usr/bin/perl
use warnings;
use strict;

my @array = ('value1','value2');

if(grep(/\bvalue1\b|\bvalue2\b/, @array)){
    print "Not Found\n";
}
else {
    print "do something\n";
}

1 Comment

0

You can also use the smart match operator:

unless( $x ~~ ['value1','value2'] )

3 Comments

I for one am going to miss "~~" if/when it goes away. There's always match::simple by @tobyink.
Just to clarify @G.Cito's comment vis-a-vis smartmatch going away...smartmatch was marked experimental in 5.18.0: "It is clear that smartmatch is almost certainly either going to change or go away in the future. Relying on its current behavior is not recommended."
@ThisSuitIsBlackNot Thanks, I tried to clarify it a bit more in my response. Channeling p5p perlmonks and @ikegami @leont it seems we can maybe hope for a much simpler version of ~~ in future versions of Perl - the behavior of which could be enhanced and extended with a utility module and the CPAN ecosystem. /me crosses fingers
-1

Your variable $a is not evaluated as a array without [INDEX] index, but is been treated as a scalar.

Two value array:

$array[0] = "X"; $array[1] = "Y";

or

@array = qw/X Y/;

Condition check using if:

if ( $array[0] ne "Your-String" || $array[1] ne "Your-String")

1 Comment

I think the way the sample code is presented assumes an @array somewhere which the value of $a is matching against. It's not the clearest example code but the OP should be the one to change it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.