[comp.lang.perl] if

me@anywhere.EBay.Sun.COM (Wayne Thompson - IR Workstation Support SE) (11/25/90)

I think it was Larry who mentioned that such a construct would be nice.
While reworking some code I replaced:

$found = 0;
for $user (@users) {
    if ($user eq $login) {
        $found = 1;
        last;
    }
}
unless ($found) {
    ...
}

with:

unless ("@users" =~ /\b$login\b/) {
    ...
}

There's no equivalent for associtive arrays though.

Wayne

tchrist@convex.COM (Tom Christiansen) (11/28/90)

In article <3992@male.EBay.Sun.COM> me@anywhere.EBay.Sun.COM (Wayne Thompson - IR Workstation Support SE) writes:
>I think it was Larry who mentioned that such a construct would be nice.

Well, an "in" operator would be nice, but there's some question on how it
would work.  Is 3.5 in 1..5?   My guess is that we'll get our "in" operator
when Larry makes the array .. into a generator function so "for (1..1e6)"
doesn't have to make the whole array first.   

I think "in" should only work on things that .. currently works with,
that is numerics and the magic alphanum strings like 'aa'..'zz'.  In
fact, "1.25 .. 3" -> (1,2,3), so I guess that 3.5 would NOT be in (1..5).

>While reworking some code I replaced:

>$found = 0;
>for $user (@users) {
>    if ($user eq $login) {
>        $found = 1;
>        last;
>    }
>}
>unless ($found) {
>    ...
>}

>with:

>unless ("@users" =~ /\b$login\b/) {
>    ...
>}

(Given @users equal to 16 names, with myself in the 10th slot).

I did 5000 runs of your first chunk of code, and it took 3.4 seconds.

The second line you offered took 5.47 seconds unmodified.  If you add a
/o, it becomes 2.82 seconds, and if you slap an eval around the whole
thing, it's just 2.1 seconds.

I think, however, that I would probably have written it the first 
time as something more like this:

	if (grep($login eq $_, @users)) {

which takes 3.2 seconds to run.  The problem is it won't stop early.
I think the regexp is quite possibly your best bet.  

>There's no equivalent for associtive arrays though.

How equivalent?  Your regexp code could be 
    
    unless (join(' ', keys %array) =~ /b$login\b/o) {

but you don't really want to do that for huge %arrays.  
It would probably be better to do something more like this:

    while (($key) = each %array) {
	if ($key eq $login) { $found++; last; }
    }


Now that I think about it, you probably could have done something
like this:

    @users{@users} = 1..@users; # OR ELSE for (@users) {$users{$_}++;}
    unless ($users{$login}) {

when doing stuff like this, I tend to keep my users in a %users array, not
a @users one, just so I can quickly check if I've seen them.  %arrays can
work as sets quite well.  

(So can bit vectors, but that's for another posting.)

--tom