Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
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 (Sage) 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 cooling their heels in the Monastery: (16)
As of 2015-07-06 18:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (80 votes), past polls