ultibuzz has asked for the wisdom of the Perl Monks concerning the following question:
Hi all, i've 5 variables and need to check if they are "" or full. i need to check all possibility of combinations, i've done it with a if elsif construct and i'm asking myself "is there not a nicer way to do it ( without goto)"
my $name;
my $vorname;
my $plz;
my $tel;
my $tel49;
if ($name) {
if ($vorname) {
if ($plz) {
if ($tel) {
if ($tel49) {
$name , $vorname , $plz , $tel and $tel49
}
$name , $vorname , $plz and $tel
}
$name , $vorname and $plz
}
$name and $vorname
}
elsif ($plz) {
if ($tel) {
if ($tel49) {
$name , $plz , $tel and $tel49
}
$name , $plz and $tel
}
$name and $plz
}
elsif ($tel) {
if ($tel49) {
$name , $tel and $tel49
}
$name and $tel
}
elsif ($tel49) {
$name and $tel49
}
only $name
}
elsif ($vorname) {
if ($plz) {
if ($tel) {
if ($tel49) {
$vorname , $plz , $tel and $tel49
}
$vorname , $plz and $tel
}
$vorname and $plz
}
only $vorname
}
elsif ($plz) {
if ($tel) {
if ($tel49) {
$plz , $tel and $tel49
}
$plz and $tel
}
only $plz
}
elsif ($tel) {
if ($tel49) {
$tel and $tel49
}
only $tel
}
elsif ($tel49) {
only $tel49
}
kd ultibuzz
Re: A Case with 5 Var's
by GrandFather (Saint) on Jan 25, 2007 at 11:10 UTC
|
A neat trick that may, or may not, help (depending on what you are trying to achieve) is to generate a bit vector:
use strict;
use warnings;
my $name = '';
my $vorname = 'full';
my $plz = 1;
my $tel = 0;
my $tel49 = undef;
my $vector = (!$name) || 2;
$vector |= (!$vorname) || 4;
$vector |= (!$plz) || 8;
$vector |= (!$tel) || 16;
$vector |= (!$tel49) || 32;
printf "%06b\n", $vector;
which sets a bit in $vector for each "true" variable. As a bonus it sets the least significant bit if any of the variables is false. Note BTW that there is a big difference between defined and "true". The sample prints:
001101
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
|
| [reply] |
|
use strict;
use warnings;
my %dispatch = (
0b000001 => \&noneTrue,
0b111110 => \&allTrue,
0b001101 => \&firstLine,
);
my $name = '';
my $vorname = 'full';
my $plz = 1;
my $tel = 0;
my $tel49 = undef;
while (<DATA>) {
chomp;
my ($name, $vorname, $plz, $tel, $tel49) = split ',';
my $vector = (!$name) || 2;
$vector |= (!$vorname) || 4;
$vector |= (!$plz) || 8;
$vector |= (!$tel) || 16;
$vector |= (!$tel49) || 32;
$dispatch{$vector}->($.) if exists $dispatch{$vector};
}
sub noneTrue {
print "None true in input line $_[0]\n";
}
sub allTrue {
print "All true in input line $_[0]\n";
}
sub firstLine {
print "Matched first line pattern at input line $_[0]\n";
}
__DATA__
,full,1,0,
first,second,3,4,
1,2,3,4,5
,,3,4,
last,,,,
Prints:
Matched first line pattern at input line 1
All true in input line 3
None true in input line 5
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
Re: A Case with 5 Var's
by dorward (Curate) on Jan 25, 2007 at 10:42 UTC
|
my @found;
foreach my $field_name (qw/name vorname plz tel tel49/) {
push(@found, $field_name) if ($my_hash{$field_name});
}
(Untested)
That will give you an array of all the fields that are set. This may or may not be helpful - you didn't say what you planned to do with the results. | [reply] [d/l] |
|
my @found = grep exists $my_hash{ $_ }, qw( name vorname plz tel tel49
+ );
Update: Good point below. Omit the exists if that's the desired behavior. MENTAL NOTE: NO POSTING OR UPDATING NODES BEFORE CAFFEINE TAKES EFFECT.
| [reply] [d/l] |
|
| [reply] |
Re: A Case with 5 Var's
by Ieronim (Friar) on Jan 25, 2007 at 10:49 UTC
|
#!usr/bin/perl
my ($name, $vorname, $plz, $tel, $tel49);
my %vars;
while (<DATA>) {
print;
chomp;
($name, $vorname, $plz, $tel, $tel49) = split /\s*,\s*/, $_, -1;
@vars{qw/name vorname plz tel tel49/} = ($name, $vorname, $plz, $t
+el, $tel49);
my @good = grep {$vars{$_}} keys %vars;
printf " %s %s good\n",
@good ? join ", ", @good : "No variables",
@good == 1 ? "is" : "are";
}
__DATA__
john, stuart, some_plz, 123456, 234557
john, stuart, some_plz, 123456,
john, stuart, some_plz,, 234557
, stuart, , 123456, 234557
, , , , 234557
,,,,
It prints:
john, stuart, some_plz, 123456, 234557
tel49, vorname, tel, plz, name are good
john, stuart, some_plz, 123456,
vorname, tel, plz, name are good
john, stuart, some_plz,, 234557
tel49, vorname, plz, name are good
, stuart, , 123456, 234557
tel49, vorname, tel are good
, , , , 234557
tel49 is good
,,,,
No variables are good
s;;Just-me-not-h-Ni-m-P-Ni-lm-I-ar-O-Ni;;tr?IerONim-?HAcker ?d;print
| [reply] [d/l] [select] |
|
If you don't actually care about the variable names, then a variation on leronim's example might do the trick:
#!/usr/bin/perl -w
use strict;
use warnings;
my @varNames = qw { name vorname plz tel tel49 };
my @vars;
while (<DATA>) {
print;
chomp;
(@vars) = split /\s*,\s*/;
print "\t";
for my $var (@varNames) {
print $var, ":", shift @vars ? "good " : "bad ";
}
print "\n\n";
}
__DATA__
john, stuart, some_plz, 123456, 234557
john, stuart, some_plz, 123456,
john, stuart, some_plz, 123456
john, stuart, some_plz,, 234557
, stuart, , 123456, 234557
,,,123456, 234557
john,,some_plz,, 234557
Which prints:
john, stuart, some_plz, 123456, 234557
name:good vorname:good plz:good tel:good tel49:good
john, stuart, some_plz, 123456,
name:good vorname:good plz:good tel:good tel49:bad
john, stuart, some_plz, 123456
name:good vorname:good plz:good tel:good tel49:bad
john, stuart, some_plz,, 234557
name:good vorname:good plz:good tel:bad tel49:good
, stuart, , 123456, 234557
name:bad vorname:good plz:bad tel:good tel49:good
,,,123456, 234557
name:bad vorname:bad plz:bad tel:good tel49:good
john,,some_plz,, 234557
name:good vorname:bad plz:good tel:bad tel49:good
--roboticus | [reply] [d/l] [select] |
Re: A Case with 5 Var's
by Melly (Chaplain) on Jan 25, 2007 at 11:59 UTC
|
If restructuring your code to use a hash is too awkward, you can assign you vars to an array and quickly check that - e.g. (untested)
$var1 = 'hello';
$var2 = 0;
$var3 = '';
@array = ($var1, $var2, $var3);
foreach(@array){
print "empty\n" if $_ eq '';
}
map{$a=1-$_/10;map{$d=$a;$e=$b=$_/20-2;map{($d,$e)=(2*$d*$e+$a,$e**2
-$d**2+$b);$c=$d**2+$e**2>4?$d=8:_}1..50;print$c}0..59;print$/}0..20
Tom Melly, pm@tomandlu.co.uk
| [reply] [d/l] [select] |
Re: A Case with 5 Var's
by ultibuzz (Monk) on Jan 25, 2007 at 12:18 UTC
|
wow great tips, and now what i want to do. i need to define a qry wich depends on the var's and is different for any possibility. can this be done with a hash ? no text file processing or so, var's are filled from keyb kd ultibuzz
| [reply] |
|
use strict;
use SQL::Abstract;
my $sql = SQL::Abstract->new;
my $table = 'customers';
my @fields = qw(name vorname plz tel);
# You shouldn't have $name, $vorname etc. but a hash
# containing the things you want:
my %where = (
name => $name,
vorname => $vorname,
);
my ($stmt, @bind) = $sql->select($table, \@fields, \%where);
print <<EOM;
-- I use the following SQL:
$stmt
-- with the following placeholders
@bind
| [reply] [d/l] |
A reply falls below the community's threshold of quality. You may see it by logging in.
|
|
I've no idea what kind of "qry" you're talking about. But let's assume you want a database query where the contents of the where clause are controlled by the existance of data items that are stored in a hash. The keys of the hash are the column names and the values are the values that are required.
In the past I've used code something like this:
my $sql = 'select col_x, col_x from a_table';
# You'll be setting this hash up from some kind of
# input to your program. I'm using variables for
# illustrative purposes.
my %cols = (
col_x => $foo,
col_y => $bar,
col_z => $baz,
);
my @where;
my @vals;
foreach (keys $cols) {
if (defined $cols{$_}) {
push @where, "$_ = ?";
push @vals, $cols{$_};
}
}
if (@where) {
$sql .= ' where ' . join(' and ', @where);
}
my $sth = $dbh->prepare($sql);
$sth->execute(@vals);
Update: Or use SQL::Abstract as Corion points out.
| [reply] [d/l] |
|
| [reply] |
|
|
|