Reputation: 8436
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);
Upvotes: 4
Views: 2329
Reputation: 378
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.
Upvotes: 2
Reputation: 385655
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");
Upvotes: 7
Reputation: 8376
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.
Upvotes: 1
Reputation: 1711
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.
Upvotes: 3
Reputation: 13842
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.
Upvotes: 0