在每个案例中使用多个值进行 PHP 切换的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1309728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 01:58:51  来源:igfitidea点击:

Best way to do a PHP switch with multiple values per case?

phpswitch-statement

提问by JasonDavis

How would you do this PHP switch statement?

你会怎么做这个 PHP switch 语句?

Also note that these are much smaller versions, the 1 I need to create will have a lot more values added to it.

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

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

Version 2:

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

UPDATE - Test Results

更新 - 测试结果

I ran some speed test on 10,000 iterations,

我对 10,000 次迭代进行了一些速度测试,

Time1: 0.0199389457703 // If statements
Time2: 0.0389049446106 //switch statements
Time3: 0.106977939606 // Arrays

Time1: 0.0199389457703 // If 语句
Time2: 0.0389049446106 //switch 语句
Time3: 0.106977939606 // 数组

采纳答案by too much php

For any situation where you have an unknown string and you need to figure out which of a bunch of otherstrings it matches up to, the only solution which doesn't get slower as you add more items is to use an array, but have all the possible strings as keys. So your switch can be replaced with the following:

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

// 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);

This doesn't look as clean as a switch(), but it is the only fastsolution which doesn't include writing a small library of functions and classes to keep it tidy. It is still very easy to add items to the arrays.

这看起来不像 . 干净switch(),但它是唯一不包括编写小型函数和类库以保持整洁的快速解决方案。向数组中添加项目仍然很容易。

回答by too much php

Version 2 does not work!!

版本 2 不起作用!!

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

is exactly the same as:

完全相同:

case True:

and that casewill be chosen for any value of $p, unless $pis the empty string.

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

||Does not have any special meaning inside a casestatement, you are not comparing $pto each of those strings, you are just checking to see if it's not False.

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

回答by karim79

Put those many values into an array and query the array, as the switch-case seems to hide the underlying semantics of what you're trying to achieve when a string variable is used as the condition, making it harder to read and understand, e.g.:

将这些许多值放入一个数组并查询该数组,因为当使用字符串变量作为条件时,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';
}

回答by Peter

For the sake of completeness, I'll point out that the broken "Version 2" logic can be replaced with a switch statement that works, and alsomake use of arrays for both speed and clarity, like so:

为了完整起见,我将指出损坏的“第 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);
}    

回答by pguardiario

Some other ideas not mentioned yet:

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

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

Someone will probably complain about readability issues with #2, but I would have no problem inheriting code like that.

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

回答by Mark Rushakoff

If anyoneelse was ever to maintain your code, they would almost certainly do a double take on version 2 -- that's extremely non-standard.

如果其他人要维护您的代码,他们几乎肯定会对版本 2 进行双重操作——这是非常不标准的。

I would stick with version 1. I'm of the school of though that case statements without a statement block of their own should have an explicit // fall throughcomment next to them to indicate it is indeed your intent to fall through, thereby removing any ambiguity of whether you were going to handle the cases differently and forgot or something.

我会坚持使用第 1 版。虽然没有自己的语句块的 case 语句应该// fall through在它们旁边有一个明确的注释,以表明它确实是你的意图,从而消除了是否存在任何歧义你会以不同的方式处理这些案件,却忘了什么的。

回答by Robert Cartaino

Version 1 is certainly easier on the eyes, clearer as to your intentions, and easier to add case-conditions to.

版本 1 显然更容易理解,更清楚你的意图,并且更容易添加案例条件。

I've never tried the second version. In many languages, this wouldn't even compile because each case labels has to evaluate to a constant-expression.

我从未尝试过第二个版本。在许多语言中,这甚至无法编译,因为每个 case 标签都必须计算为常量表达式。

回答by Josh Leitzel

I definitely prefer Version 1. Version 2 may require less lines of code, but it will be extremely hard to read once you have a lot of values in there like you're predicting.

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

(Honestly, I didn't even know Version 2 was legal until now. I've never seen it done that way before.)

(老实说,直到现在我都不知道第 2 版是合法的。我以前从未见过这样做过。)

回答by tomfumb

No version 2 doesn't actually work but if you want this kind of approach you can do the following (probably not the speediest, but arguably more intuitive):

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

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

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

回答by liljoshu

Nowadays you can do...

现在你可以做...

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