[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [MacPerl] find value in array



At 7:03 PM 10/14/00, g3pb wrote:
>is there a way other then using foreach to determie if an array contains a
>particular value. in AppleScript it would be
>
>if list contains value then
>     -- do stuff
>end if

This got several suggestions, and some discussion. Below are two 
little subroutines that could be used for the original poster's 
purpose.


At 9:31 AM 10/16/00, Ronald J Kimball wrote:
>On Sun, Oct 15, 2000 at 09:59:18PM -0700, Bruce Van Allen wrote:
>
>>  Here's a subroutine that will work for all cases as long as the
>>  character '~' isn't expected in the data:
>>
>>  sub inlist {
>>     my ($value, @list) = @_;
>>     $_ = join('~', @list);
>>     return unless /^($value)~/ || /^(.*~$value)~/ || /^(.*~$value)$/;
>>     my $chunk = $1;
>>     \($chunk =~ tr/~/~/)
>>  }
>>
>>  Can the pattern matching could be optimized? I used the || syntax to
>>  be sure to get the right thing in $1.
>
>
>What if you added a ~ to the beginning and end of the string?
>
>
>sub inlist {
>     my($value, @list) = @_;
>     local($_) = '~' . join('~', @list) . '~';
>
>     return unless /^(.*?~$value)~/;
>
>     my $chunk = $1;
>     $chunk =~ tr/~// or '0 but true';  # :)
>}
>

Adding the '~' at the start has the effect of increasing the number 
of transliterations by 1, making the sub return the item number, not 
the array index. This could be OK, as long as the user remembers to 
subtract 1 when using it as an index.

So here are two usable subs. Both use the syntax inlist($value, 
@list), and return undef if $value is not in the list, or the 
position number (item number) -- not the index -- of the list item in 
which $value is found. So you could do this:

if inlist($value, @list) {
    # do stuff
}

or

$item_num = inlist($value, @list);
$something_else = $list[$item_num-1];

The subs:

sub inlist {
     my $value = shift;
     local($_) = '~' . join('~', @_) . '~';
     return unless /^(.*?~$value)~/;
     my $chunk = $1;
     $chunk =~ tr/~//;
}

sub inlist2 {
     my %testhash; @testhash{@_} = (0..@_);
     return unless exists $testhash{$_[0]};
     $testhash{$_[0]}
}

Both return the item number, so subtract 1 to get the array index. Or 
modify the sub to subtract 1 and return a *reference* to the number. 
Returning a reference is necessary to avoid a false value if the 
value being searched for happens to appear in the first list item, 
which would have the index 0; if tested for truth 0 returns false, 
whereas a reference to it would return true. Then you have to 
dereference the number to use it as the array index.


# sample:

#!perl -w

my @list = qw/oil water grease fluid/;
my @values = qw/water grease oil fluid waiter greas fluide oil water/;

foreach $value (@values) {
     if ($item_num = inlist($value, @list)) {
         print "1  $value is item #", $item_num, " of the list.\n"
     } else {
     	print "0  $value not found in the list.\n"
     }
}

## Works as long as '~' isn't in the data
sub inlist {
     my $value = shift;
     local($_) = '~' . join('~', @_) . '~';
     return unless /^(.*?~$value)~/;
     my $chunk = $1;
     $chunk =~ tr/~//;
}

## Alternative:
# sub inlist {
#	my %testhash; @testhash{@_} = (0..@_);
#	return unless exists $testhash{$_[0]};
#	$testhash{$_[0]}
#}

__END__


HTH

1;

- Bruce

__Bruce_Van_Allen___bva@cruzio.com__Santa_Cruz_CA__

# ===== Want to unsubscribe from this list?
# ===== Send mail with body "unsubscribe" to macperl-request@macperl.org