3
foreach my $f($query->param) {
    foreach my $v($query->param($f)) {
        switch($f) {
            case 'a' {
                switch($v) {
                    case 1 { code1; }
                    case 2 { code2; }
                    case 3 { code3; }
                }

            case 'b' {
                switch($v) {
                    case 1 { code4; }
                    case 2 { code5; }
                }

            case 'c' {
                switch($v) {
                    case 1 { code6; }
                    case 2 { code7; }
                    case 3 { code8; }
                    case 4 { code9; }
                }
            }
        }
    }
}
Lem0n
  • 1,217
  • 1
  • 14
  • 22
  • 1
    Looks pretty simple already. And it's hard to tell, since you are not showing what happens in the "code" section. – TLP Jul 31 '11 at 19:38
  • 1
    Every time you write `code;` does it denote a unique code block? If not then please update your question to show which code blocks are unique and which are duplicates. – Dave Jul 31 '11 at 19:41
  • yes, it's a unique code for each case – Lem0n Jul 31 '11 at 19:42
  • 4
    A quick sidenote: as of Perl 5.12, the switch statement [has been deprecated](http://stackoverflow.com/questions/2630547/why-is-the-switch-module-deprecated-in-perl), and been replaced by [`given/when`](http://perldoc.perl.org/perlsyn.html#Switch-statements). – Mike Jul 31 '11 at 19:53
  • 4
    given/when were in 5.10, and you really should use them, not Switch.pm – ysth Jul 31 '11 at 19:58

3 Answers3

12

Above all... DO NOT USE Switch.pm. If you are using Perl 5.10 or newer, given/when is a native switch statement.

A dispatch table is the solution you seek. http://www.perlmonks.org/?node_id=587072 describes dispatch tables, a technique for executing code via a hash based on some value matching the hash key.

Edit, example:

my %dispatch_table = (
    'a' => {
        '1' => sub { code1; },
        '2' => sub { code2; },
        '3' => sub { code3; },
    'b' => {
        '1' => \&some_sub,
        '2' => sub { code4; },
    }
)

if ( exists( $dispatch_table{$f} ) and exists( $dispatch_table{$f}{$v} ) ) {
    $dispatch_table{$f}{$v}->();
}
else {
    # some default
}
mikegrb
  • 1,183
  • 5
  • 13
3

Put it in a "dispatch table":

my %code = (
    a => {
        1 => sub { code1 },
        2 => sub { code2 },
        3 => sub { code3 },
    },
    b => {
        1 => sub { code4 },
        2 => sub { code5 },
    },
    c => {
        1 => sub { code6 },
        2 => sub { code7 },
        3 => sub { code8 },
        4 => sub { code9 },
    },
);

Then once you have $f and $v, call the correct subroutine:

$code{$f}{$v}->();
tadmc
  • 3,714
  • 16
  • 14
1

Depending on what you mean by "simplified", you might consider something like this (if you're sure that neither $f nor $v can contain a ','):

foreach my $f ($query->param) {
    foreach my $v ($query->param($f)) {
        switch ("$f,$v") {
            case "a,1" { code; }
            case "a,2" { code; }
            case "a,3" { code; }

            case "b,1" { code; }
            case "b,2" { code; }

            case "c,1" { code; }
            case "c,2" { code; }
            case "c,3" { code; }
            case "c,4" { code; }
        }
    }   
}

(I'm assuming that all the occurrences of code; are actually different.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Why the restriction on the comma? If there was a $f such that $f equals "x,y" and there was a case "x,y,1" and "x,y,2" to address it, this would still work; wouldn't it? – Dave Jul 31 '11 at 19:48
  • 2
    @Dave: because you couldn't differentiate `$f="x,y";$v="z"` from `$f="x";$v="y,z"` – ysth Jul 31 '11 at 19:59