необычная троичная операция - PullRequest
14 голосов
/ 17 апреля 2010

Меня попросили выполнить эту операцию использования троичного оператора:

$test='one';

echo $test == 'one' ? 'one' :  $test == 'two' ? 'two' : 'three';

Который печатает два (проверено с помощью php).

Я все еще не уверен в логике этого. Пожалуйста, кто-нибудь может сказать мне логику для этого.

Ответы [ 7 ]

15 голосов
/ 17 апреля 2010

Ну, а? и: имеют одинаковый приоритет, поэтому PHP будет анализировать слева направо, оценивая каждый бит по очереди:

echo ($test == 'one' ? 'one' :  $test == 'two') ? 'two' : 'three';

First $test == 'one' возвращает true, поэтому первые парены имеют значение 'one'. Теперь вторая троичная фигура оценивается так:

'one' /*returned by first ternary*/ ? 'two' : 'three'

'one' равно true (непустая строка), поэтому 'two' является окончательным результатом.

7 голосов
/ 17 апреля 2010

В основном интерпретатор оценивает это выражение слева направо, поэтому:

echo $test == 'one' ? 'one' :  $test == 'two' ? 'two' : 'three';

интерпретируется как

echo ($test == 'one' ? 'one' :  $test == 'two') ? 'two' : 'three';

И выражение в паратезах оценивается как истинное, поскольку и «один», и «два» не являются нулевой / о / другой формой ложного. Так что если бы это выглядело так:

echo $test == 'one' ? FALSE :  $test == 'two' ? 'two' : 'three';

Это напечатало бы три. Чтобы все работало нормально, вы должны забыть о комбинировании троичных операторов и использовать обычные ifs / switch для более сложной логики или, по крайней мере, использовать скобки, чтобы интерпретатор понимал вашу логику, а не выполнять проверку стандартным способом LTR:

echo $test == 'one' ? 'one' :  ($test == 'two' ? 'two' : ($test == 'three' ? 'three' : 'four'));

//etc... It's not the most understandable code... 

//You better use:
if($test == 'one')
    echo 'one';
else { //or elseif()
...
}

//Or:
switch($test) {
    case 'one':
        echo 'one';
        break;
    case 'two':
        echo 'two';
        break;
//and so on...
}
5 голосов
/ 17 апреля 2010

Работает правильно при использовании скобок:

<?
 $test='one';
 echo $test == 'one' ? 'one' :  ($test == 'two' ? 'two' : 'three');

Я не понимаю это на 100%, но без скобок для интерпретатора утверждение должно выглядеть так:

echo ($test == 'one' ? 'one' :  $test == 'two') ? 'two' : 'three';

результат первого условия, кажется, возвращается как результат всей троичной операции.

1 голос
/ 17 апреля 2010

Тернарные операторы выполняются в порядке появления, поэтому у вас действительно есть:

echo ($test == 'one' ? 'one' :  $test == 'two') ? 'two' : 'three';
1 голос
/ 17 апреля 2010

Я думаю, что это оценивается так:

echo ($test == 'one' ? 'one' :  $test == 'two') ? 'two' : 'three';

($ test == 'one'? 'One': $ test == 'two') не ноль / ноль, поэтому 'two' является логическим выводом

если вы хотите, чтобы он работал правильно, напишите:

echo $test == 'one' ? 'one' :  ($test == 'two' ? 'two' : 'three');
1 голос
/ 17 апреля 2010

PHP * S документация говорит:

Примечание: Рекомендуется, чтобы вы избегали "суммирования" троичных выражений . Поведение PHP при использовании более одного тернарного оператора в одном выражении неочевидно:

Пример # 3 Неочевидное троичное поведение

<?php
// on first glance, the following appears to output 'true'
echo (true?'true':false?'t':'f');

// however, the actual output of the above is 't'
// this is because ternary expressions are evaluated from left to right

// the following is a more obvious version of the same code as above
echo ((true ? 'true' : false) ? 't' : 'f');

// here, you can see that the first expression is evaluated to 'true', which
// in turn evaluates to (bool)true, thus returning the true branch of the
// second ternary expression.
?>

Если вы поставите круглые скобки вокруг ложного утверждения, оно напечатает one:

echo $test == 'one' ? 'one' :  ($test == 'two' ? 'two' : 'three');
0 голосов
/ 17 апреля 2010

Вложенные троичные операции брутто! Приведенное выше объяснение показывает, почему.

В основном это логика:

is $test == 'one'

  if TRUE then echo 'one'

  else is $test == 'two'

      if TRUE then echo 'two'

      else echo three
...