每种情况下使用多个值进行PHP切换的最佳方法?

时间:2009-08-21 01:52:38

标签: php switch-statement

你会如何做这个PHP switch语句?

另请注意,这些是更小的版本,我需要创建的1将添加更多的值。

版本1:

switch ($p) { 
    case 'home': 
    case '': 
        $current_home = 'current';
    break; 

    case 'users.online': 
    case 'users.location': 
    case 'users.featured': 
    case 'users.new': 
    case 'users.browse': 
    case 'users.search': 
    case 'users.staff': 
        $current_users = 'current';
    break;

    case 'forum': 
        $current_forum = 'current';
    break; 
} 

第2版:

switch ($p) { 
    case 'home': 
        $current_home = 'current';
    break; 

    case 'users.online' || 'users.location' || 'users.featured' || 'users.browse' || 'users.search' || 'users.staff': 
        $current_users = 'current';
    break;

    case 'forum': 
        $current_forum = 'current';
    break; 
} 

更新 - 测试结果

我在10,000次迭代中运行了一些速度测试,

时间1:0.0199389457703 //如果陈述
时间2:0.0389049446106 //切换语句
时间3:0.106977939606 //数组

16 个答案:

答案 0 :(得分:50)

对于你有一个未知字符串的任何情况,你需要找出它匹配的一堆其他字符串中的哪一个,唯一的解决方案是,当你添加更多时,它不会变慢items是使用数组,但将所有可能的字符串作为键。因此,您的开关可以替换为以下内容:

// used for $current_home = 'current';
$group1 = array(
        'home'  => True,
        );

// used for $current_users = 'current';
$group2 = array(
        'users.online'      => True,
        'users.location'    => True,
        'users.featured'    => True,
        'users.new'         => True,
        'users.browse'      => True,
        'users.search'      => True,
        'users.staff'       => True,
        );

// used for $current_forum = 'current';
$group3 = array(
        'forum'     => True,
        );

if(isset($group1[$p]))
    $current_home = 'current';
else if(isset($group2[$p]))
    $current_users = 'current';
else if(isset($group3[$p]))
    $current_forum = 'current';
else
    user_error("\$p is invalid", E_USER_ERROR);

这看起来不像switch()一样干净,但它是唯一的 fast 解决方案,它不包括编写一个小函数和类库来保持整洁。将项添加到数组中仍然非常容易。

答案 1 :(得分:25)

版本2不起作用!!

case 'users.online' || 'users.location' || ...

与:

完全相同
case True:

并且case将被选择为$p的任何值,除非$p是空字符串。

||case语句中没有任何特殊含义,您没有将$p与每个字符串进行比较,您只是检查它是否不是{{1} }}

答案 2 :(得分:8)

将这些值放入数组并查询数组,因为switch-case似乎隐藏了当字符串变量用作条件时你想要实现的内容的基本语义,使得它更难以阅读和理解,例如:

$current_home = null;
$current_users = null;
$current_forum = null;

$lotsOfStrings = array('users.online', 'users.location', 'users.featured', 'users.new');

if(empty($p)) {
    $current_home = 'current';
}

if(in_array($p,$lotsOfStrings)) {
    $current_users = 'current';
}

if(0 === strcmp('forum',$p)) {
    $current_forum = 'current';
}

答案 3 :(得分:4)

如果任何人其他人一直在维护您的代码,他们几乎肯定会对版本2进行双重处理 - 这非常不合标准。

我会坚持使用版本1.虽然那些没有自己语句块的案例陈述应该在他们旁边有一个明确的// fall through评论,以表明它确实是你的意图通过,从而消除了你是否会以不同的方式处理案件和忘记或其他事情的任何含糊不清。

答案 4 :(得分:4)

为了完整起见,我将指出破坏的“版本2”逻辑可以替换为有效的switch语句,并且使用数组来提高速度和清晰度,像这样:

// used for $current_home = 'current';
$home_group = array(
    'home'  => True,
);

// used for $current_users = 'current';
$user_group = array(
    'users.online'      => True,
    'users.location'    => True,
    'users.featured'    => True,
    'users.new'         => True,
    'users.browse'      => True,
    'users.search'      => True,
    'users.staff'       => True,
);

// used for $current_forum = 'current';
$forum_group = array(
    'forum'     => True,
);

switch (true) {
    case isset($home_group[$p]):
        $current_home = 'current';
        break;
    case isset($user_group[$p]):
        $current_users = 'current';
        break;
    case isset($forum_group[$p]):
        $current_forum = 'current';
        break;
    default:
        user_error("\$p is invalid", E_USER_ERROR);
}    

答案 5 :(得分:3)

版本1在眼睛上更容易,更清楚你的意图,更容易添加案例条件。

我从未尝试过第二个版本。在许多语言中,这甚至都不会编译,因为每个案例标签都必须评估为常量表达式。

答案 6 :(得分:3)

尚未提及的其他一些想法:

switch(true){ 
  case in_array($p, array('home', '')): 
    $current_home = 'current'; break;

  case preg_match('/^users\.(online|location|featured|new|browse|search|staff)$/', $p):
    $current_users = 'current'; break;

  case 'forum' == $p:
    $current_forum = 'current'; break; 
}

有人可能会抱怨#2的可读性问题,但我继承这样的代码没有问题。

答案 7 :(得分:1)

我绝对更喜欢版本1.版本2可能需要更少的代码行,但是一旦你有很多值就像你预测的那样很难阅读。

(老实说,到目前为止,我甚至都不知道第2版是合法的。我以前从未见过这样做过。)

答案 8 :(得分:1)

没有版本2实际上不起作用,但如果你想要这种方法,你可以做以下事情(可能不是最快,但可以说更直观):

switch (true) {
case ($var === 'something' || $var === 'something else'):
// do some stuff
break;
}

答案 9 :(得分:0)

我认为版本1是要走的路。阅读和理解起来要容易得多。

答案 10 :(得分:0)

if( in_array( $test, $array1 ) )
{
    // do this
}
else if( stristr( $test, 'commonpart' ) )
{
    // do this
}
else
{
    switch( $test )
    {
        case 1:
            // do this
            break;
        case 2:
            // do this
            break;
        default:
            // do this
            break;
    }
}

答案 11 :(得分:0)

variable variables 结合使用会为您提供更多灵活性:

<?php
$p = 'home'; //For testing

$p = ( strpos($p, 'users') !== false? 'users': $p);
switch ($p) { 
    default:
        $varContainer = 'current_' . $p; //Stores the variable [$current_"xyORz"] into $varContainer
        ${$varContainer} = 'current'; //Sets the VALUE of [$current_"xyORz"] to 'current'
    break;

}
//For testing
echo $current_home;
?>

要了解更多信息,请查看variable variables以及我提交给php手册的示例:
示例1 http://www.php.net/manual/en/language.variables.variable.php#105293
示例2 http://www.php.net/manual/en/language.variables.variable.php#105282

PS:这个示例代码是 SMALL AND SIMPLE ,就像我喜欢的那样。它已经过测试并且也可以使用

答案 12 :(得分:0)

现在你可以做...

switch ([$group1, $group2]){
    case ["users", "location"]:
    case ["users", "online"]:
        Ju_le_do_the_thing();
        break;
    case ["forum", $group2]:
        Foo_the_bar();
        break;
}

答案 13 :(得分:0)

也许

        switch ($variable) {
        case 0:
            exit;
            break;
        case (1 || 3 || 4 || 5 || 6):
            die(var_dump('expression'));
        default:
            die(var_dump('default'));
            # code...
            break;
    }

答案 14 :(得分:0)

您只是在寻找字符串中的常见模式。我原以为正则表达式会是一种更有效的方法,因为 PHP 使用 preg_match 实现了这一点,所以编写的代码很少,而且速度可能会大大加快。例如:

case preg_match('/^users./'):
// do something here
break;

答案 15 :(得分:0)

从 PHP 文档中,您可以这样做:https://www.php.net/manual/en/control-structures.switch.php#41767

$input = 'users.online';
$checked = null;
        
switch (true):
    case ($input === 'home'):
        $checked = 'ok 1';
        break;

    case (in_array($input , ['users.online', 'users.location', 'users.featured', 'users.browse', 'users.search', 'users.staff'])):
        $checked = 'ok 2';
        break;

    case ($input === 'forum'):
        $checked = 'ok 3';
        break;
endswitch;

echo $checked;