4

Because I can't find a convenient way to check if $str is in @array, I'm trying to make one myself, but it is not working.

I guess it is because of the mix-up of array and string. It keeps giving 0 to $str. Please let me know how to fix it.

use 5.010;
use strict;
use warnings;

sub ifin {
    my (@array, $str) = @_;
    for my $i (@array) {
        if ($i eq $str) {
            return 1;
        }
    }
    return 0;
}

my @f = (1, 2, 3, 4);
my $k = 1;
print ifin(@f, $k);
3

5 Answers 5

7

You can't pass arrays to subs, only lists of scalars.

ifin(@f, $k);

is the same as

ifin($f[0], $f[1], $f[2], $f[3], $k);

because @f evaluates to a list of its elements.

One way of passing an array to a sub is to pass a reference.

sub ifin {
   my ($array, $str) = @_;
   for my $e (@$array) {
      return 1 if $e eq $str;
   }

   return 0;
}

my @f = (1,2,3,4);
my $k = 1;
print(ifin(\@f, $k), "\n");

By the way, that can also be written as:

my @f = (1,2,3,4);
my $k = 1;
print(( grep { $_ eq $k } @f ) ? 1 : 0, "\n");

You could keep the existing calling convention by using pop.

sub ifin {
   my $str = pop(@_);
   for my $e (@_) {
      return 1 if $e eq $str;
   }

   return 0;
}

my @f = (1,2,3,4);
my $k = 1;
print(ifin(@f, $k), "\n");
Sign up to request clarification or add additional context in comments.

2 Comments

$i is usually used for indexes, so I used $e (for "element").
Added alternative that allows you to keep the currentl calling convention.
3

You may want to check any in the List::MoreUtils package, you just use it like:

use List::MoreUtils 'any';

my @f= qw(1 2 3 4);
my $k=10;

print "yes\n" if( any { $_ == $k } @f );

check the documentation in:

perldoc List::MoreUtils.

Comments

2

How about $str ~~ @arr in a smartmatch? That's available in Perl 5.10.

use 5.010;
use strict;
use warnings;

my $str = 'three';
my @arr = qw(zero one two three four);
my @badarr = qw(zero one two four eight);

say '$str ', $str ~~ @arr? 'is' : 'is not', ' in $arr.';
say '$str ', $str ~~ @badarr? 'is' : 'is not', ' in $badarr.';

Output, as expected:

$str is in $arr.
$str is not in $badarr.

Comments

1

You could pass your arguments in reverse order (print ifin($k, @f);), so array is going last. When you catch them now from subroutine, string comes first and array gets populated with any list items after it.

Comments

0

You could use a prototype, but those are kind of brittle. I would pass in a reference to @f as the first argument, like this:

use 5.010;
use strict;
use warnings;

sub ifin
{
my ($array,$str)=@_;
 for my $i (@$array)
 {
  if ($i eq $str)
  {
   return True
  }
 }
 return False
}


my @f= (1,2,3,4);
my $k=1;
print ifin(\@f,$k);

For a long list, you avoid making a copy of every list element as well.

1 Comment

Technically, you are still passing a reference even if you have the prototype do the referencing for you :)

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.