Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

something like switch(case) in Perl

by agustina_s (Sexton)
on Jan 23, 2002 at 08:02 UTC ( [id://140807]=perlquestion: print w/replies, xml ) Need Help??

agustina_s has asked for the wisdom of the Perl Monks concerning the following question:

Hi Perlmonks. I really need your help..... Is there something like
switch(case) case A :do somehing case B :do some other thing
in Perl??? I only know that in C we have switch(case) like that. In this case I have a hash table %house containing around 30 elements. And for each of the key value of the hash I must check each key.. eg:
foreach $person (keys %house){ { if $person eq "CC"){ print "My name "; p_CC();} elsif $person eq "AB"){ print "AB "; p_AB();} elsif $person eq "CD"){ print "My friend "; p_CD();} .... ##for the whole element else ... }
It takes a long time to compile my program. I really wish there is something better to make my prog faster. Please help me.... Thanks a lot.

Replies are listed 'Best First'.
(RhetTbull) Re: something like switch(case) in Perl
by RhetTbull (Curate) on Jan 23, 2002 at 08:23 UTC
    As others have said here, perl does not have a built-in switch statement. However, TheDamian has written an excellent module (which will be a standard core module in future perl versions) called Switch.pm. It's very nice and perlish in the way it handles things (e.g. it doesn't treat everything like an int as the 'C' switch does). For example (from the module docs):
    use Switch; switch ($val) { case 1 { print "number 1" } case "a" { print "string a" } case [1..10,42] { print "number in list" } case (@array) { print "number in list" } case /\w+/ { print "pattern" } case qr/\w+/ { print "pattern" } case (%hash) { print "entry in hash" } case (\%hash) { print "entry in hash" } case (\&sub) { print "arg to subroutine" } else { print "previous case not true" } }

    Update: Here's an example similar to yours that might get you started. However, as talexb and japhy both mentioned, using coderefs in your hash might be a cleaner way of doing this.

    use strict; use warnings; use Switch; my %house = ('CC' => 'My Name', 'AB' => 'AB Name', 'CD' => 'My friend', 'EF' => 'Who?'); foreach my $person (keys %house) { print "$person: "; switch($person) { case 'AB' { print "Mine!\n" } case 'CC' { print "Yours!\n" } case 'CD' { print "Friend!\n" } case %house { print "in house, but don't know him!\n" } else { print "I don't know what to do!\n" } } }
      As a word of caution, Switch is *not* a great module; yes, it replicates what C has, but it's not efficient nor impervious to bugs. As I believe the lastest word on Perl 6 from Larry has implied, the lack of a good switch block in Perl 5 is very much apparent.

      Keep this in mind when working with this. Switch might work, but be prepared to find weird things happening if you ask it for too much.

      -----------------------------------------------------
      Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
      "I can see my house from here!"
      It's not what you know, but knowing how to find it if you don't know that's important

      Thanks... Will it be faster using the switch statement or will it be just the same?
Re: something like switch(case) in Perl
by japhy (Canon) on Jan 23, 2002 at 08:26 UTC
    You might want to use another hash with the same keys, and code references as values:
    my %actions = ( CC => sub { print "My name "; p_CC(); }, AB => sub { print "AB "; p_AB(); }, CD => sub { print "My friend "; p_CD(); }, ); for (keys %house) { $actions{$_}->(); }

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: something like switch(case) in Perl
by grep (Monsignor) on Jan 23, 2002 at 08:15 UTC
    No too hard. Use RE's and $_ (well sort of :) ).
    SWITCH: foreach (keys %house){ #Note: the key is stuffed in $_ /^person$/ and do { print "My name "; #Note: the Regex works on $_ p_CC(); next SWITCH; } /^AB$/ and do { print "AB "; p_AB(); next SWITCH;} }


    BTW this is a FAQ - 'perldoc -q switch' which will lead you to How do I create a switch or case statement.

    grep
    grep> cd pub
    grep> more beer
      Thanksss
      Hi Grep... I want ask about the switch statement that you have suggested.. About the speed... will it be just the same with:
      If(...=~...){ do something } elsif(....=~)( do some other thing } ... else {...}
      Since it also compares the $_ with /.../. Thanks...
      Straight comparisions ('eq' or '==') will always be faster than regexp's. (You can try to make your regexp's faster by anchoring and using literials)

      The main focus should not be speed at the cost of maintainibilty. If it looks cleaner and reads well go with that solution. Ovid has written an excellent post about Premature Optimization.

      grep
      grep> cd pub
      grep> more beer
Re: something like switch(case) in Perl
by talexb (Chancellor) on Jan 23, 2002 at 08:16 UTC
    Sorry, there currently is no switch statement in Perl. It's coming in Perl 6, but for now you'll have to use a cascading if .. elsif .. elsif .. else configuration. (And yes, it really is spelled elsif.)

    However, your code looks like you could use a loop and some kind of data structure.

    my @Data = ( {person => "CC", who => "My name ", func => \&p_CC }, {person => "AB", who => "AB ", func => \&p_AB }, {person => "CD", who => "friend", func => \&p_CD }, ); PERSON: foreach $person ( keys %house ) { foreach ( @Data ) { if ( $_->{ person } eq $person ) { print $_->{ who }; &{ $_ }->{ func }(); next PERSON; } } # Handle else here. }
    If the person in %House is found, the print and function call will be executed, and we'll continue with the next key in the loop. Otherwise, we exhaust the possibilities of the table and fall through to the bottom of the inner loop.

    And I would put the most likely array elements near the top (if possible) in order to reduce the execution time.

    That's it!

    --t. alex

    "Of course, you realize that this means war." -- Bugs Bunny.

Re: something like switch(case) in Perl
by Veachian64 (Scribe) on Jan 23, 2002 at 08:17 UTC
    Nope, there's no switch statement in Perl (at least not yet), but a number of ways to fake it are here.
Re: something like switch(case) in Perl
by Anonymous Monk on Jan 23, 2002 at 09:03 UTC
    augustina_s: It is great that you are taking the time to learn. To help you learn easier, please go read How to RTFM a couple of times, and then begin your life in perldoc, many of us live there ;)

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (1)
As of 2024-04-25 05:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found