web-dev-qa-db-ja.com

ケースごとに複数の値を使用してPHPスイッチを実行する最良の方法は?

この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回の反復で速度テストを実行しましたが、

Time1:0.0199389457703 // Ifステートメント
Time2:0.0389049446106 // switchステートメント
Time3:0.106977939606 //配列

67
JasonDavis

不明な文字列があり、other文字列のどれに一致するかを把握する必要がある状況では、アイテムを追加しても遅くならない唯一の解決策は配列を使用しますが、すべての可能な文字列をキーとして使用します。したがって、スイッチは次のものに置き換えることができます。

// 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解決策であり、整頓を保つための関数とクラスの小さなライブラリの作成を含みません。配列にアイテムを追加するのはまだ非常に簡単です。

51
too much php

バージョン2は動作しません!!

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

以下とまったく同じです。

case True:

$pが空の文字列でない限り、$pの任意の値に対してcaseが選択されます。

||caseステートメント内で特別な意味はありません。$pをこれらの各文字列と比較するのではなく、単にFalseでないかどうかを確認するだけです。

25
too much php

これらの多くの値を配列に入れ、配列を照会します。スイッチケースは、文字列変数を条件として使用するときに達成しようとしているものの基本的なセマンティクスを隠しているように見えるため、読みやすく、理解しにくくなっています:

$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';
}
8
karim79

anyone elseがコードを保守する場合、バージョン2をほぼ確実に二重に取ります-これは非常に非標準です。

私はバージョン1に固執します。しかし、私は、自分自身のステートメントブロックのないcaseステートメントには、その横に明示的な// fall throughコメントがあり、それが本当にあなたの意図通りであることを示します。ケースを異なる方法で処理して忘れてしまったのか、それとも何かを忘れたのかというあいまいさを取り除きます。

4
Mark Rushakoff

完全を期すために、壊れた「バージョン2」ロジックは動作するswitchステートメントに置き換えることができ、alsoは速度と明瞭さの両方のために配列を使用することを指摘します。 :

 //に使用$ current_home = 'current'; 
 $ home_group = array(
 'home' => True、
); 
 
 // $ 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、
); 
 
 // $ 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_er ror( "\ $ pは無効です"、E_USER_ERROR); 
} 
4
Peter

まだ言及されていない他のアイデア:

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の読みやすさの問題について文句を言うでしょうが、そのようなコードを継承しても問題はありません。

4
pguardiario

バージョン1は、確かに目には簡単で、意図が明確で、ケース条件を簡単に追加できます。

私は2番目のバージョンを試したことがない。多くの言語では、各ケースラベルは定数式に評価される必要があるため、これはコンパイルされません。

3
Robert Cartaino

実際には機能しないバージョン2はありませんが、この種のアプローチが必要な場合は、次のことを実行できます(おそらく最も高速ではありませんが、おそらくより直感的です)。

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

1
tomfumb

私は間違いなくバージョン1を好みます。バージョン2は必要なコード行が少ないかもしれませんが、予測しているような値がたくさんあると読むのは非常に難しくなります。

(正直なところ、私はバージョン2が今まで合法であることさえ知りませんでした。それが以前にそのように行われるのを見たことがありません。)

1
Josh Leitzel

変数変数と組み合わせてスイッチを使用すると、柔軟性が向上します。

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

詳細については、checkout variable variables およびphpマニュアルに送信した例:
例1http://www.php.net/manual/en/language.variables.variable。 php#10529
例2http://www.php.net/manual/en/language.variables.variable。 php#105282

PS:このサンプルコードはSMALL AND SIMPLEで、私が好きな方法です。テスト済みで動作します

0
Omar

バージョン1を使用する方法だと思います。読みやすく理解しやすいです。

0
Josh Curren

多分

        switch ($variable) {
        case 0:
            exit;
            break;
        case (1 || 3 || 4 || 5 || 6):
            die(var_dump('expression'));
        default:
            die(var_dump('default'));
            # code...
            break;
    }
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;
    }
}
0
AnOldMan

今日はあなたができる...

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