在 PHP 中堆叠多个三元运算符

Posted

技术标签:

【中文标题】在 PHP 中堆叠多个三元运算符【英文标题】:Stacking Multiple Ternary Operators in PHP 【发布时间】:2021-12-30 04:27:20 【问题描述】:

这是我写的:

 $Myprovince = (
($province == 6) ? "city-1" :
($province == 7) ? "city-2" :
($province == 8) ? "city-3" :
($province == 30) ? "city-4" : "out of borders"
);

但是对于每个字段,我都得到了 city-4 的值。我想使用三元运算符而不是 switch/if,因为我想试验一下,看看它是如何完成的。

这段代码有什么问题?

【问题讨论】:

您是否有理由不想只使用if / elseifswitch 你需要更多的括号才能工作。按照 Marc 的建议,使用 switch 不推荐使用具有复杂嵌套条件的三元运算符,原因很充分......因为它们充满了问题,而且很难识别错误。你刚刚发现了这个!如果您真的知道如何使用它们,您就不会寻求帮助!那么在这种情况下为什么还要使用三元运算符呢? 在下方查看您的答案:***.com/questions/5235632/5235721#5235721 上帝,拜托,我不会在实时脚本中使用这种方法,永远不会,你现在好点了吗?只是好奇如何使用它:D 【参考方案1】:

另一个解决方案是在 php 8 中使用 the match statement 引入的:

$Myprovince = match ($province) 
    6 => "city-1",
    7 => "city-2",
    8 => "city-3",
    30 => "city-4",
    default => "out of borders",
;

它本质上只是一个不太冗长的switch 语句,非常适合简单的赋值。也可以添加多个条件:

$Myprovince = match ($province) 
    4, 5, 6 => "city-1",
    7, 9, 10 => "city-2",
    8 => "city-3",
    30 => "city-4",
    default => "out of borders",
;

【讨论】:

【参考方案2】:

我认为在 PHP 中编写嵌套三元运算符更易读的方式是这样的:

$myprovince =
    $province ==  6 ? "city-1" : (
    $province ==  7 ? "city-2" : (
    $province ==  8 ? "city-3" : (
    $province == 30 ? "city-4" : "out of borders" )));

您只需计算左括号 (() 的数量,并在最后一行末尾添加相同数量的右括号 ())。

另一种选择是使用单行 if/elseif/else,正如已经建议的那样 - 但是,我会像这样在视觉上格式化它们以提高可读性:

if      ($province == 6)  $myprovince = "city-1";
elseif  ($province == 7)  $myprovince = "city-2";
elseif  ($province == 8)  $myprovince = "city-3";
elseif  ($province == 30) $myprovince = "city-4";
else                      $myprovince = "out of borders";

【讨论】:

【参考方案3】:

我今天也遇到了同样的问题。其他人已经给出了可接受的解决方案。我只是强调一个班轮如果。在我看来更具可读性。

if ($province == 6) $Myprovince = 'city-1';
elseif ($province == 7) $Myprovince = 'city-2';
elseif ($province == 8) $Myprovince = 'city-3';
elseif ($province == 30) $Myprovince = 'city-4';
else $Myprovince = 'out of borders';

【讨论】:

这是一个比开关更清洁的解决方案。 开关很丑,是的,但最好是带有isset() 检查的查找数组——简单而干净。【参考方案4】:

其他人已经提出了正确的做法,但如果你真的想使用三元运算符,你需要使用括号:

$province = 7;
 $Myprovince = (
 ($province == 6) ? "city-1" :
  (($province == 7) ? "city-2" :
   (($province == 8) ? "city-3" :
    (($province == 30) ? "city-4" : "out of borders")))
 );

Updated Link

【讨论】:

不寒而栗我会为你输入的勇气+1,但不能让自己“认可”这样一个可怕的事情...... 这确实是“正确”的做法。不过,我永远不会尝试这样的事情。 坚持不懈绝对值得+1 @Mac Taylor:你使用了错误的工具来完成这项工作。没有什么可说的了。您也可以使用字符串连接'a'.'b'.'c' 创建字符串'abc',但为什么要这样做呢?尽情享受为您的三元野兽添加新城市的乐趣,别忘了数数以匹配括号! 我认为拒绝使用链式三元作为编程模式并不是一个好的回应。它可以在多种语言中“正确”实现简洁明了的代码,并且因为它生成表达式,有时它是快速修复某些东西的唯一方法。我使用引号是因为虽然 PHP 设计者确实做出了 asinine 选择以使其三元运算符左关联,但事实是有据可查的。【参考方案5】:

三元运算符从左到右求值。所以如果你没有正确地对表达式进行分组,你会得到一个意想不到的结果。

PHP's advice is [docs]:

建议您避免“堆叠”三元表达式。在单个语句中使用多个三元运算符时 PHP 的行为并不明显。

您的代码实际上被评估为:

(
    (
        (
            $province == 6 ? "city-1" : $province == 7
        ) ? "city-2" : 
        $province == 8
    ) ? "city-3" : $province == 30
) ? "city-4" : "out of borders";

它应该在哪里

$province == 6 ? "city-1" : (
    $province == 7 ? "city-2" : (
        $province == 8 ? "city-3" : (
           $province == 30 ? "city-4" : "out of borders"
        )
    )
);

这段代码可能看起来不错,但有人会阅读它,他们需要比他们应该的更多的时间来理解这段代码在做什么。


这样的话你会更好:

$map = array( 6 = >'city-1', 
              7 => 'city-2', 
              8 => 'city-3', 
             30 => 'city-4');

$Myprovince = "out of borders";

if(array_key_exists($province, $map)) 
    $Myprovince = $map[$province];

或者正如他的评论中提到的@Jonah:

$Myprovince = isset($map[$province]) ? $map[$province] : 'out of borders';

【讨论】:

用这个让它更短:$Myprovince = isset($map[$province]) ? $map[$province] : 'out of borders'; ;-) @Jonah: True :D 我想我想尽可能远离三元运算符 ;) 对于您的编辑,我相信其他行是前几行的 c 语句。注意,没有分号。这几乎就是:($province == 6) ? "city-1" : ($province == 7) ? "city-2" : ($province == 8) ? "city-3" : ($province == 30) ? "city-4" : "out of borders"; @Phoenix:是的,我注意到并修复了它。我对这一切?: 感到非常困惑;) 请注意,PHP 8 禁用了没有显式括号的嵌套三元组。【参考方案6】:

我知道这是一个关于 PHP 的问题,但由于这只是一个教育练习,我认为您可能有兴趣了解 Ruby 和 javascript 的实际行为方式。

鲁比:

ree-1.8.7-2012.02 :009 > def foo x
ree-1.8.7-2012.02 :010?>   x == 1 ? "city 1" : x == 2 ? "city 2" : "out of borders"
ree-1.8.7-2012.02 :011?>   end
 => nil
ree-1.8.7-2012.02 :012 > foo 1
 => "city 1"
ree-1.8.7-2012.02 :013 > foo 2
 => "city 2"
ree-1.8.7-2012.02 :014 > foo 3
 => "out of borders"

Javascript:

> function f(x)  return x == 1 ? "city 1" : x == 2 ? "city 2" : "out of borders"; 
undefined
> f(1)
"city 1"
> f(2)
"city 2"
> f(3)
"out of borders"

【讨论】:

耸耸肩 ...当然Ruby和Javascript已经做到了...毕竟它们是编程语言^_^【参考方案7】:

有些人建议使用 switch 语句或 if/else 语句。但我会改用数组,以使其更易于维护和阅读:

$provinces = array (
    6 => 'city-1',
    7 => 'city-2',
    8 => 'city-3',
    30 => 'city-4'
);

// then you can call:

$Myprovince = isset($provinces[$province]) ? $provinces[$province] : 'out of borders';

为什么?

代码最终可能会更容易管理。也许有一天你会想从数据库中添加那些省到城市的映射......等等。这将很难用一堆 switch/case 语句来维护。

【讨论】:

我会喜欢你的。绝对是最佳答案! 这个不错。不过要小心“内存不足”问题。【参考方案8】:

尝试使用更多括号:

$Myprovince = (
($province == 6) ? "city-1" :
(($province == 7) ? "city-2" :
(($province == 8) ? "city-3" :
(($province == 30) ? "city-4" : "out of borders"
))));

您的代码存在三元运算符优先级问题。

但我认为你真的应该放弃这个运算符并尝试使用switch

【讨论】:

【参考方案9】:

改用开关。三元运算符确实不应该用于多个条件,因为它们很快就会变得非常难以理解。

switch ($province) 
    case 6:
        $Myprovince = 'city-1';
        break;
    case 7:
        $Myprovince = 'city-2';
        break;
    case 8:
        $Myprovince = 'city-3';
        break;
    case 30:
        $Myprovince = 'city-4';
        break;
    default:
        $Myprovince = 'out of borders';

【讨论】:

【参考方案10】:

不要在这类事情上滥用三元运算符。它使调试几乎无法进行。为什么不做类似的事情

switch($province) 
    case 6: $Myprovince = "city-1"; break;
    case 7: ...

或者只是一些链式 if/then/else

if ($province == 6) 
     $Myprovince = "city-1";
 elseif ($province = ...) 
   ...

【讨论】:

我不是说过我坚持使用三元运算符是因为某些原因吗? @Mac Taylor:不,你没有。是什么原因?默默无闻? @Felix:也许是调试受虐狂? 与这些相比,三元的最大好处是它允许进行单个变量赋值。

以上是关于在 PHP 中堆叠多个三元运算符的主要内容,如果未能解决你的问题,请参考以下文章

如何在三元运算符中编写多个语句?

PHP三元运算符

php 三元运算符实例详细介绍

PHP 三元运算符说明

PHP三元速记运算符中使用isset()时获取变量值

php 中 三元运算和 IF语句 运行速度