【问题标题】:Would an array be more effective than a switch case for this scenario?在这种情况下,数组会比开关盒更有效吗?
【发布时间】:2015-12-28 21:27:55
【问题描述】:

我正在根据来自 API 的输入显示星级评分(注意:仅显示,根本不接收评分)。以下代码完全按照我的需要工作,但它是一个非常大的逻辑,感觉它可以被大量简化。

我在这里阅读了一些其他票证,这些票证表明使用数组可能比开关盒更有效。但是因为逻辑取决于一个数字范围内的真值(比如大于 2.5 但小于 3)之间的每种情况,所以我不确定在这种情况下数组是否可以工作。

底线是:这段代码能否以某种方式大规模简化?

$stars = 3.5;

switch ($stars) {
  case ($stars > 1 && $stars <= 1.5):
    $star2 = 'dashicons-star-half';
    $star3 = 'dashicons-star-empty';
    $star4 = 'dashicons-star-empty';
    $star5 = 'dashicons-star-empty';
    break;
  case($stars > 1.5 && $stars <= 2):
    $star2 = 'dashicons-star-filled';
    $star3 = 'dashicons-star-empty';
    $star4 = 'dashicons-star-empty';
    $star5 = 'dashicons-star-empty';
    break;
  case($stars > 2 && $stars <= 2.5):
    $star2 = 'dashicons-star-filled';
    $star3 = 'dashicons-star-half';
    $star4 = 'dashicons-star-empty';
    $star5 = 'dashicons-star-empty';
    break;
  case($stars > 2.5 && $stars <= 3):
    $star2 = 'dashicons-star-filled';
    $star3 = 'dashicons-star-filled';
    $star4 = 'dashicons-star-empty';
    $star5 = 'dashicons-star-empty';
    break;
  case($stars > 3 && $stars <= 3.5):
    $star2 = 'dashicons-star-filled';
    $star3 = 'dashicons-star-filled';
    $star4 = 'dashicons-star-half';
    $star5 = 'dashicons-star-empty';
    break;
  case($stars > 3.5 && $stars <= 4):
    $star2 = 'dashicons-star-filled';
    $star3 = 'dashicons-star-filled';
    $star4 = 'dashicons-star-filled';
    $star5 = 'dashicons-star-empty';
    break;
  case($stars > 4 && $stars <= 4.5):
    $star2 = 'dashicons-star-filled';
    $star3 = 'dashicons-star-filled';
    $star4 = 'dashicons-star-filled';
    $star5 = 'dashicons-star-half';
    break;
  case($stars > 4.5):
    $star2 = 'dashicons-star-filled';
    $star3 = 'dashicons-star-filled';
    $star4 = 'dashicons-star-filled';
    $star5 = 'dashicons-star-filled';
    break;
  default:
  $star2 = 'dashicons-star-empty';
  $star3 = 'dashicons-star-empty';
  $star4 = 'dashicons-star-empty';
  $star5 = 'dashicons-star-empty';
}

?>
 <div class="wporg-ratings" title="<?php echo $stars; ?> out of 5 stars" style="color:#e6b800;">
   <span class="dashicons dashicons-star-filled"></span>
   <span class="dashicons <?php echo $star2; ?>"></span>
   <span class="dashicons <?php echo $star3; ?>"></span>
   <span class="dashicons <?php echo $star4; ?>"></span>
   <span class="dashicons <?php echo $star5; ?>"></span>
 </div>

【问题讨论】:

  • 看起来填充星星的数量比实际的 $star 值少 1 对吗?意思是如果 $stars = 3.5 那么将有 2 个填充和 1 个半星。
  • @AbraCadaver 如果你低头看 html,第一个星总是被填满的。 ^^
  • 是的,@Jon 是对的。在这个系统中,评论不可能少于 1 星,因此第 1 星总是被填满,这就是为什么它总是以 $star2 开头。

标签: php arrays switch-statement case


【解决方案1】:

我认为不需要数组或开关。您可以使用 for 循环,并根据循环变量检查 $stars 值以查看应该使用哪个图标。

<div class="wporg-ratings" title="<?php echo $stars; ?> out of 5 stars" style="color:#e6b800;">
<?php
// for loop: one iteration for each of five possible stars
// (for loops are generally best for repeating code a specific number of times)
for ($i=0; $i < 5; $i++) {
    if ($stars <= $i ) {
        // empty stars are displayed when the iterator (i) is >= the star value
        echo  '<span class="dashicons dashicons-star-empty"></span>';
    } elseif ($stars <= $i + 0.5) {
        // half stars are displayed for star values between i and i+0.5 
        echo  '<span class="dashicons dashicons-star-half"></span>';
    } else {
        // whole stars are displayed when the star value is > i+0.5
        echo  '<span class="dashicons dashicons-star-filled"></span>';
    }
}
?>
</div>

为了帮助理解这为何有效,请在循环中取一个理论值。我们可以使用您问题中的3.5

  • 第一次迭代:3.5 > 0, 3.5 > 0.5,所以你得到 else 值(实心星)
  • 第二次迭代:3.5 > 1, 3.5 > 1.5,所以得到 else 值(实心星)
  • 第三次迭代:3.5 > 2, 3.5 > 2.5,所以得到else值(实心星)
  • 第四次迭代:3.5 > 3, 3.5 = 3.5,所以得到 elseif 值(半星)
  • 第五次迭代:3.5

【讨论】:

  • 哇。这完美无缺。你能详细说明一下为什么/如何工作吗?我以前见过这样的循环,但我很困惑如何总是用这个循环吐出适量的星星,以及它如何确切地知道何时触发半星或空星。一定会在您的澄清中将此标记为已接受的答案。
  • @MattCromwell 我编辑了答案。我希望解释和示例对您有所帮助。
  • 完美@dont-panic 感谢您提供更多详细信息。帮助我更好地理解。
【解决方案2】:

这里是快速版本:

$stars = 3.5;
$d = array(
    ($stars >= 1.0) ? 'dashicons-star-filled' : (($stars >= 0.5) ? 'dashicons-star-half' : 'dashicons-star-empty'),
    ($stars >= 2.0) ? 'dashicons-star-filled' : (($stars >= 1.5) ? 'dashicons-star-half' : 'dashicons-star-empty'),
    ($stars >= 3.0) ? 'dashicons-star-filled' : (($stars >= 2.5) ? 'dashicons-star-half' : 'dashicons-star-empty'),
    ($stars >= 4.0) ? 'dashicons-star-filled' : (($stars >= 3.5) ? 'dashicons-star-half' : 'dashicons-star-empty'),
    ($stars >= 5.0) ? 'dashicons-star-filled' : (($stars >= 4.5) ? 'dashicons-star-half' : 'dashicons-star-empty')
);
echo '<div class="wporg-ratings" title="' . $stars . ' out of 5 stars" style="color:#e6b800;">';
foreach ($d as $value) echo '<span class="dashicons ' . $value . '"></span>';
echo '</div>';

它和你原来的逻辑不一样(当第一个星总是被填充时),但你可以用它作为方向

下一步可能是将重复的代码移动到函数中

【讨论】:

  • 我考虑过三元运算符,但没有考虑将它们与数组结合使用。这很有创意。谢谢!
【解决方案3】:

另一种可能性是定义一个哈希数组。假设数组中的每个元素都包含“最小值和三个字符串”,并且数组按升序排序。您的 if/then 逻辑可以被通过该数组的循环替换,并尽快中断。

但是: “清晰胜过所有其他问题。”如果代码工作并且可以合理维护,谁在乎它是否臭?

您现有的代码可以通过注意 if 条件的前半部分可以省略来简化以消除任何值“落入裂缝”的可能性:如果您达到第二种情况,则必须是真的值大于 1.5,以此类推。

【讨论】:

  • 是的,我愿意保留代码原样,因为它可以工作并且可读性极强。但我知道必须有一种更有效的方法来产生相同的结果,这很可能也会有更好的性能。我认为@dont-panic 有一个解决方案可以教会我很多东西,它的性能要好得多,而且整体代码要少得多。
猜你喜欢
  • 1970-01-01
  • 2023-01-31
  • 2012-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
相关资源
最近更新 更多