【问题标题】:php switch case statement to handle rangesphp switch case语句来处理范围
【发布时间】:2012-01-16 06:51:18
【问题描述】:

我正在解析一些文本并根据一些规则计算权重。所有角色的权重都相同。这会使 switch 语句很长我可以在 case 语句中使用范围吗?

我看到一个提倡关联数组的答案。

$weights = array(
[a-z][A-Z] => 10,
[0-9] => 100,
['+','-','/','*'] => 250
);
//there are more rules which have been left out for the sake of clarity and brevity
$total_weight = 0;
foreach ($text as $character)
{
  $total_weight += $weight[$character];
}
echo $weight;

实现这样的目标的最佳方法是什么? 有没有类似于 php 中的 bash case 语句的东西? 在关联数组或 switch 语句中写下每个单独的字符肯定不是最优雅的解决方案,还是唯一的选择?

【问题讨论】:

    标签: php range switch-statement


    【解决方案1】:

    好吧,你可以在 switch 语句中设置范围,例如:

    //just an example, though
    $t = "2000";
    switch (true) {
      case  ($t < "1000"):
        alert("t is less than 1000");
      break
      case  ($t < "1801"):
        alert("t is less than 1801");
      break
      default:
        alert("t is greater than 1800")
    }
    
    //OR
    switch(true) {
       case in_array($t, range(0,20)): //the range from range of 0-20
          echo "1";
       break;
       case in_array($t, range(21,40)): //range of 21-40
          echo "2";
       break;
    }
    

    【讨论】:

    • 非常好!但没有人能接受这一点。 40 票反对 1 票。打赌你赚了一些床位。
    • 只是为了解释开关的第一位中的(true),现在这是所有比较中的other side,即数组中的1,2还是3?如果是,它将返回一个true。而true,就是开关上面那一行里面的condition,所以可以用
    • 这是一个很好的解决方案,是迄今为止我所见过的最好的解决方案。如果您正在寻找一个很好的答案,请忽略已接受的答案。多年来我一直想要这样的东西,但从未想过实际看看它是否可能,这是我见过的避免无限循环或 if/elseif 结构的最佳方法。我的案例:case stri_str($test_value,'test string'): 就像一个魅力。
    • 这是一个很好的解决方案,但在我的情况下,我的范围是从 0 到 1000 和五个级别(所以数字可以在 0 到 5000 之间)。 range() 的解决方案将生成五个包含 1000 个元素的数组,那么这个解决方案是不是个好主意?如果有人过来并可以回答这个问题,请随意:)
    【解决方案2】:
    $str = 'This is a test 123 + 3';
    
    $patterns = array (
        '/[a-zA-Z]/' => 10,
        '/[0-9]/'   => 100,
        '/[\+\-\/\*]/' => 250
    );
    
    $weight_total = 0;
    foreach ($patterns as $pattern => $weight)
    {
        $weight_total += $weight * preg_match_all ($pattern, $str, $match);;
    }
    
    echo $weight_total;
    

    *更新:使用默认值 *

    foreach ($patterns as $pattern => $weight)
    {
        $match_found = preg_match_all ($pattern, $str, $match);
        if ($match_found)
        {
            $weight_total += $weight * $match_found;
        }
        else
        {
            $weight_total += 5; // weight by default
        }
    }
    

    【讨论】:

    • 在此如何添加默认情况。说找不到东西,我想给它分配一个固定的权重。
    • 发现与任何案例都不匹配的东西。现在它没有分配任何权重,但我想要一个非零默认值。
    【解决方案3】:

    您可以使用正则表达式指定字符范围。这样可以避免编写非常长的 switch case 列表。例如,

    function find_weight($ch, $arr) {
        foreach ($arr as $pat => $weight) {
            if (preg_match($pat, $ch)) {
                return $weight;
            }   
        }   
        return 0;
    }
    
    $weights = array(
    '/[a-zA-Z]/' => 10, 
    '/[0-9]/'    => 100,
    '/[+\\-\\/*]/'   => 250 
    );
    //there are more rules which have been left out for the sake of clarity and brevity
    $total_weight = 0;
    $text = 'a1-';
    foreach (str_split($text) as $character)
    {
      $total_weight += find_weight($character, $weights);
    }
    echo $total_weight; //360
    

    【讨论】:

      【解决方案4】:

      很多不同的方法来做到这一点。

       $var = 0;
       $range_const = range(10,20);
       switch ($var) {
          case 1: $do = 5; break; # 1
          case 2: $do = 10; break; # 2
          case 3:
          case 4:
          case 5: $do = 15; break; # 3, 4, 5
          default:
            if ($var > 5 && $var < 10) { # High performance (6..9)
              $do = 20;
            } else if (in_array($var, $range_const, true)) { # Looks clear (10..20)
              $do = 25;
            } else { # NOT in range 1..20
              $do = -1;
            }
      }
      print($do);
      

      没有直接范围 X..Y 比较,因为 $var 在每一步都检查为真,但这允许像这样做一些不错的作弊......

      $in = create_function('$a,$l,$h', 'return $a>=$l && $a<=$h;');
      $var = 4;
      switch (true) {
        case ($var === 1): echo 1; break;
        case ($var === 2): echo 2; break;
        case $in($var, 3, 5): echo "3..5"; break;
        case $in($var, 6, 10): echo "6..10"; break;
        default: echo "else";
      } 
      

      【讨论】:

        【解决方案5】:

        如果您有更复杂的条件,您可以将它们包装在一个函数中。这是一个过于简单的例子:

        $chartID = 20;
        $somethingElse = true;
        
        switch (switchRanges($chartID, $somethingElse)) {
          case "do this":
              echo "This is done";
              break;
          case "do that":
              echo "that is done";
              break;
          default:
              echo "do something different";
        }
        
        function switchRanges($chartID, $somethingElse = false)
        {
            if (in_array($chartID, [20, 30]) && $somethingElse === true) {
                return "do this";
            }
            if (in_array($chartID, [20, 50]) && $somethingElse === false) {
                return "do that";
            }
        }
        

        【讨论】:

          【解决方案6】:

          我想我会用一种简单的方式来做。

          switch($t = 100){
              case ($t > 99 && $t < 101):
                  doSomething();
                  break;
          }
          

          【讨论】:

          • doSomething() 总是会被调用,因为 "switch($t = 100)" 将 100 分配给 $t
          • 这是不正确的代码,因为你不能拥有case x&lt;10:,你只能拥有case 10