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

Hi,
I have a page where there are 3 options (say Option A,B and C) which the user can select , in any combination and permutation, based on which I have to select a particular product code. (for e.g. the user can select any one of the 3, any 2 of the 3 or none of the options). Rather than solve this using the cumbersome if-else construct or the switch case construct, I was wondering if there was any optimized way of handling this...

Replies are listed 'Best First'.
Re: optimized switch case
by Zaxo (Archbishop) on Jan 03, 2002 at 06:43 UTC

    You could map the options into 1, 2, and 4, then add them. That will be insensitive to permutations, and provide a unique number for each combination. The selection can just use the number as an array index.

    my @selections = ( 'Feeblizer', 'Cervical Vorbalizer', 'Cortical Vorbalizer', 'Corticocervical Extravorbalizer', 'Lumbar Vorbalizer', 'Cervicolumbar Extravorbalizer', 'Corticolumbar Extravorbalizer', 'Hypervorbalizer' ) $_ = $optstring # wherever that comes from my $options = m/A/ + 2 * m/B/ + 4 * m/C/; print $selections[$options];

    After Compline,
    Zaxo

      thank you,
      That worked like a dream. I did have one follow-up question though.In my case, I just had 3 choices which the user could choose from.What if there were a dozen or more choices which could be selected in any combination...hard-coding an array for that scenario would be very cumbersome, wouldnt it ? is there a separate approach to take in the case ?

        Yes, it gets very unwieldy for larger numbers of options. That is unavoidable if the options are mutually dependent and each combination must give a unique response. That is probably a sign to refactor what the options represent.

        If you really have that many distinct choices, chances are they are independent enough to benefit from the treatment suggested by Fastolfe and clintp. The numeric mapping I suggested doesn't need to be used as an array index. An option number can be tested with bitwise operators when logic is needed, and magically masked numbers can be used as hash keys.

        After Compline,
        Zaxo

Re: optimized switch case
by Fastolfe (Vicar) on Jan 03, 2002 at 06:40 UTC
    A couple of thoughts:
    $_ = &fetch_input; $picked{$_}++ foreach split //; &do_a if $picked{a}; &do_b if $picked{b}; ... # or, simpler: $_ = &fetch_input; &do_a if /a/; &do_b if /b/; ...
      # Or more maintainable! %options=( a => sub { do_this() or that() }, b => \&do_that, c => sub { do_nut() }, ); foreach(split(//, &fetch_input)) { &{$options{$_}} if exists $options{$_}; }
      I suggest not getting people in the habit of using the &foo syntax for calling functions because of the implicit argument passing that they are probably not aware of. Even if you know the gotchas, a lot of people do not.

        tilly, could you please clarify? Are you referring to the passing of the package name or object reference when calling a function like $bar->foo()? Using the ampersand bypasses this behavior, so I'm not sure what you're getting at.