Testing against a list of values ?

B

- Bob -

I coded the following, which works but is lengthy:

if ( ($temp ne "a")
and( $temp ne "x" )
and ( $temp ne "y" ) ){ ....}

What's a more Perl-like and compact way to code something like this ?
 
G

Gunnar Hjalmarsson

- Bob - said:
I coded the following, which works but is lengthy:

if ( ($temp ne "a")
and( $temp ne "x" )
and ( $temp ne "y" ) ){ ....}

What's a more Perl-like and compact way to code something like this ?

Check out the grep() function.

perldoc -f grep

if ( grep( $temp eq $_, @values ) == 0 ) { ... }
 
U

Uri Guttman

PG> #!perl

PG> while (<DATA>)
PG> {
PG> if ($_ =~ tr/axy// == 0)
PG> { print $_; }
PG> }

as usual moronzilla gets it wrong. try that code with 'ax' or any string
of length > 1 and at least one of 'axy'. it won't behave as the OP
wants.

the correct answer is to use a hash. plenty of examples in this group so
search it with google.

uri
 
U

Uri Guttman

PG> Irrelevant. Your comments do not comply with the originating author's
PG> stated parameters. You are practicing deceit, more succinct, you are
PG> lying to readers which is much in keeping with your years long history
PG> and reputation as being amongst the worst of trolls spreading ignorance
PG> and discontent within this discussion group.

he never stated that the input would always be a single character. you
assumed so in your broken code. so your code is wrong as it usually is
as it doesn't account for bad data. it does account for bad code as it
came from you.

as for trolling and such, when have you last published a cpan module,
gave a talk at a conference, been hired to train people in perl or any
of a number of perl things? not in anyone's lifetime here. so please go
back to your loonie been as you did for a blessed few months.

uri
 
G

grocery_stocker

"loony bin"

Ha! Ha! You are so predictable, such a comical bozo troll!

You are THE laughing stock of the Perl community and have
been so, for many years.

I know I shouldn't interject, however, Uri knows what he is talking
about, you don't. Besides, a simple google search on Uri shows that he
is pretty well respected in the Perl community.
 
M

Mirco Wahab

- Bob - said:
I coded the following, which works but is lengthy:

if ( ($temp ne "a")
and( $temp ne "x" )
and ( $temp ne "y" ) ){ ....}

What's a more Perl-like and compact way to code something like this ?

Depending on your real intend (check only
characters - or longer strings), I'd saythat 'grep'
would be 'perlish' (solution already posted by others)

You could make it 'more descriptive' by wrapping it
into a subroutine, like

...

sub NOT_IN { ! grep $_[0] =~ /$_/, @_[1..@_-1] }


my $temp ="bz";

if ( NOT_IN $temp => qw' a x y ' ) {
print "$temp doesn't contain one\n"
# ....
}

...


Regards

M.
 
D

Dr.Ruud

- Bob - schreef:
I coded the following, which works but is lengthy:

if ( ($temp ne "a")
and( $temp ne "x" )
and ( $temp ne "y" ) ){ ....}

What's a more Perl-like and compact way to code something like this ?

For example

/^[axy]$/

or

/^(?:a|x|y)$/

where the latter has room for longer values. You can mix'm too:

if ( $temp =~ m!^(?: [ny] | no | yes )$!x ) {...}
 
U

Uri Guttman

MD> On Thu, 05 Apr 2007 01:58:15 +0200, Gunnar Hjalmarsson

MD> unless ( grep $temp eq $_, @values) { ... }

MD> But seriously, in this case hash look up is probably better...

MD> (too bad there's not a syntactically sweet enough way to make an array
MD> or a list into a hash(ref) with, say, undef values. In this case I can
MD> think of

MD> unless ( { map { $_ => 1 } @values}->{$temp} ) { ... } # )

and that rebuilds the anon hash each time which is not nice if it is
called more than once. maybe in a cgi or single shot script it would be
ok.

a simple way to make a hash of keys with undef values is:

my %isa_foo ;
@isa_foo{ @values } = () ;

i think i have seen tricks (randal?) on how to merge those line and i
bet abigail or damian could do it with an anon hash. but that is getting
to wacky for my taste. whenever i have a list of things to test against,
i usually need the list as an array too so making an array of foo and a
hash of isa_foo is best IMO (michele: see, i shifted there!)

uri
 
U

Uri Guttman

MD> Yes, yes, yes. I don't feel a *compelling* need for such a beast as
MD> that I hinted to in the other post. But occasionally I miss it.
MD> Precisely when I *want* to check if if a single value is in a list,
MD> and want to do so *only once*, possibly in one *single statement*.

MD> Well, a situation that springs to mind is this: the other day I wanted
MD> to check if a coderef is lvalue'd but attributes::get() returns a list
MD> of the attributes defined on a ref, so I'm exactly under the
MD> circumstances described above. Basically I may want something short
MD> enough to be used as in

MD> if ( islvalued($ref) ) { ... }

then List::Util::first is your friend. building a temp hash from a list
and then looking it up is at least O(N) (more caps!) as it has to scan
all the keys. first is O(N) but will scan on average only half of the
keys.

if ( first { $_ eq 'lvalue' } attributes::get($ref) ) { ... }

the hash test is almost always better when you check it more than
once. and as i said i use it if i have the list of keys in advance since
saying $isa_foo{$key} is nice and readable.

uri
 
G

Gunnar Hjalmarsson

Uri said:
a simple way to make a hash of keys with undef values is:

my %isa_foo ;
@isa_foo{ @values } = () ;

i think i have seen tricks (randal?) on how to merge those line

my %isa_foo = map { $_ => undef } @values;

Is that a trick? ;-)
 
U

Uri Guttman

GH> my %isa_foo = map { $_ => undef } @values;

GH> Is that a trick? ;-)

nope. i know that map idea from way back and mention it in my article on
hash slices. the wacky trick was doing that for an anon hash or some
other thing that needed strange ref munging. it was very fugly but
amusing and i can't recall who posted it nor would i know how to search
for it easily. not a problem since i wouldn't use that wacko code in
production.

uri
 
X

xhoster

Uri Guttman said:
GH> my %isa_foo = map { $_ => undef } @values;

GH> Is that a trick? ;-)

nope. i know that map idea from way back and mention it in my article on
hash slices. the wacky trick was doing that for an anon hash or some
other thing that needed strange ref munging. it was very fugly but
amusing and i can't recall who posted it nor would i know how to search
for it easily. not a problem since i wouldn't use that wacko code in
production.

Perhaps something like this:

@$_{@values}=() foreach (\my %$isa_foo);

Xho
 
D

Dr.Ruud

Uri Guttman schreef:
a simple way to make a hash of keys with undef values is:

my %isa_foo ;
@isa_foo{ @values } = () ;


IIRC there was a difference between the result of that and this:

my %isa_foo ;
@isa_foo{ @values } = () x @values ;

(undef as status and undef as value)
 
U

Uri Guttman

R> Uri Guttman schreef:
R> IIRC there was a difference between the result of that and this:

R> my %isa_foo ;
R> @isa_foo{ @values } = () x @values ;

R> (undef as status and undef as value)

yep. you can tell the difference in the amount of storage used and
probably with some internal probing with a scalar::util func or
something.

a hash entry can be totally empty and it will return an undef if
accessed. or it can have a proper sv in the entry which is undef
itself. i am not sure of any other direct way to get the undef slot but
the assignment of an empty list to a slice. but there probably is one
and i don't know it or some module can do it.

and in both cases you test for a key in the set with exists. some like
to assign 1 or some true value so they can just do a boolean test and
drop the exists. either way is fine with me.

uri
 
U

Uri Guttman

x> Perhaps something like this:

x> @$_{@values}=() foreach (\my %$isa_foo);

that looks like what i recall and you can see why i would never use it
in production. :) it was to declare a scalar to hold a hash ref and
assign boolean keys in one line.

uri
 
P

Peter J. Holzer

R> Uri Guttman schreef:

R> IIRC there was a difference between the result of that and this:

R> my %isa_foo ;
R> @isa_foo{ @values } = () x @values ;

R> (undef as status and undef as value)

yep. you can tell the difference in the amount of storage used and
probably with some internal probing with a scalar::util func or
something.

I can't see a difference with perl 5.8.0 or 5.8.8 on Linux:


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

my %x;

my (@a) = (1 .. $ARGV[1]);

my $m0 = mem();
if ($ARGV[0] eq '1') {
@x{@a} = (1) x @a;
} elsif ($ARGV[0] eq 'lx') {
@x{@a} = () x @a;
} elsif ($ARGV[0] eq 'le') {
@x{@a} = ();
}
print mem() - $m0, "\n";

sub mem {
open(my $f, '<', "/proc/$$/status");
while (<$f>) {
return $1 if (/VmSize:\s+(\d+) kB/);
}
}

yoyo:~/tmp 10:57 126% ./foo 1 100000
10520
yoyo:~/tmp 10:57 127% ./foo lx 100000
9116
yoyo:~/tmp 10:57 128% ./foo le 100000
9116

and in both cases you test for a key in the set with exists. some like
to assign 1 or some true value so they can just do a boolean test and
drop the exists. either way is fine with me.

Assigning 1 does take a bit more memory.

hp
 
U

Uri Guttman

R> my %isa_foo ;
R> @isa_foo{ @values } = () x @values ;
PJH> I can't see a difference with perl 5.8.0 or 5.8.8 on Linux:

PJH> sub mem {
PJH> open(my $f, '<', "/proc/$$/status");
PJH> while (<$f>) {
PJH> return $1 if (/VmSize:\s+(\d+) kB/);

i wouldn't use a vmem thingy but try it with devel::size (iirc) which
will tell you the actual ram used by a perl structure.

PJH> Assigning 1 does take a bit more memory.

so maybe it does use the undef flag in the hash entry in both cases. it
would be a nice optimization. i just recall they did different things
because of the generated code or whatever. in any case assigning an
empty list will be faster than making a list of undefs with x or map.

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top