Beefy Boxes and Bandwidth Generously Provided by pair Networks Cowboy Neal with Hat
There's more than one way to do things
 
PerlMonks  

A Case with 5 Var's

by ultibuzz (Monk)
on Jan 25, 2007 at 10:17 UTC ( #596442=perlquestion: print w/ replies, xml ) Need Help??
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

Comment on A Case with 5 Var's
Download Code
Re: A Case with 5 Var's
by dorward (Curate) on Jan 25, 2007 at 10:42 UTC

    Use a hash instead of five scalars. Then you can do:

    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.

      Or more succinctly:

      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.

        The original code doesn't consider an empty string to be "found", but exists will.

Re: A Case with 5 Var's
by Ieronim (Friar) on Jan 25, 2007 at 10:49 UTC
    Of course, you don't need to use this incredible elsif :)

    Just save your variables as values in a hash and use a simple grep:

    #!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
      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
Re: A Case with 5 Var's
by GrandFather (Cardinal) 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

      sounds interessting, so i need to check the vector bit pattern to generate a matching qry
      and this i woud do again with if and co ;/ because i don't know another way
      kd ultibuzz

        It depends a lot on where you want to go with this. One technique would be to use a hash to generate a dispatch table. Consider:

        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
Re: A Case with 5 Var's
by Melly (Hermit) 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
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

      What kind of query? If you want to generate an SQL query from a hash, there is SQL::Abstract, which does just that:

      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

        its an qry for a local unique system wich is not public, it needs defined stuff so i need to check if a var is filled or not so i can create a exact matching qry

        example: only $name and $plz is filled with Mueller and 55555 both are strings btw, then the qry looks like
        ::5544$nameGDFTxxxxx$plz::0:
        for each possibility is another qry defined ;/
        kd ultibuzz

      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.

        i'm testing a combined hash and bit solution wich untill now looks great,
        thx for the great help and examples
        kd ultibuzz

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://596442]
Approved by BrowserUk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (7)
As of 2014-04-19 06:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (478 votes), past polls