这段 Perl 代码能简化吗?

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; }
                }
            }
        }
    }
}

1
看起来已经很简单了。但是很难说,因为你没有展示“代码”部分发生了什么。 - TLP
1
每次你写 code;,它是否表示一个独特的代码块?如果不是,请更新你的问题以显示哪些代码块是唯一的,哪些是重复的。 - Dave
是的,它是每个案例的唯一代码。 - Lem0n
4
一个快速的提示:从 Perl 5.12 开始,switch语句已被弃用,并被given/when取代。 - Mike
4
在5.10版本中,如果可以的话,你真的应该使用它们,而不是Switch.pm。 - ysth
3个回答

12
首先...不要使用Switch.pm。如果您正在使用Perl 5.10或更新版本,则可以使用given/when作为本地switch语句。
调度表是您所需的解决方案。http://www.perlmonks.org/?node_id=587072描述了调度表,这是一种通过哈希匹配执行代码的技术。
编辑,示例:
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
}

我也打算建议使用调度表。 - Dallaylaen
1
@ysth,你不是“flush out”一个答案,而是“flesh out”一个答案 :-) http://www.urbandictionary.com/define.php?term=flush%20out - tadmc
@tadmc,如果这是一个非常糟糕的答案,你可能会这么做。 - cjm

3
把它放在“分发表”里:
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 },
    },
);

然后,一旦您拥有$f和$v,调用正确的子例程:
$code{$f}{$v}->();

抱歉mikegrb,当我回来投票时,我把它和你的答案搞混了。 - Lem0n

1
根据您对“简化”的理解,您可以考虑类似于以下内容(如果您确定 $f 和 $v 都不包含 ','):
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; }
        }
    }   
}

(我假设所有code;的出现实际上是不同的。)

为什么要限制逗号的使用?如果存在一个$f$,使得$f$等于“x,y”,并且有一个情况“x,y,1”和“x,y,2”需要处理,这样做仍然有效,不是吗? - Dave
2
@Dave:因为你无法区分$f="x,y";$v="z"$f="x";$v="y,z" - ysth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接