сравнение массивов в PHP - интересное поведение - PullRequest
6 голосов
/ 26 июня 2011

Первый пример:

$x = array("a" => 1, "b" => 2); 
$y = array("b" => 1, "a" => 2);
$xLessY = ($x < $y);
$xGreaterY = ($x > $y);
var_dump($xLessY, $xGreaterY);

Результат : $ xLessY = true , $ xGreaterY = true

Второй пример:

$x = array("a" => 2, "b" => 1); 
$y = array("b" => 2, "a" => 1);
$xLessY = ($x < $y);
$xGreaterY = ($x > $y);
var_dump($xLessY, $xGreaterY);

Результат : $ xLessY = false , $ xGreaterY = false

Согласнок документации по http://docs.php.net/manual/en/language.operators.comparison.php:

, если ключ от операнда 1 не найден в операнде 2, тогда массивы несравнимы, в противном случае - сравнивают значение по значению

В нашем случае каждыйключ из массива $ x присутствует в массиве $ y, поэтому $ x и $ y сравнимы.См. Также пример из документации:

// Arrays are compared like this with standard comparison operators
function standard_array_compare($op1, $op2)
{
    if (count($op1) < count($op2)) {
        return -1; // $op1 < $op2
    } elseif (count($op1) > count($op2)) {
        return 1; // $op1 > $op2
    }
    foreach ($op1 as $key => $val) {
        if (!array_key_exists($key, $op2)) {
            return null; // uncomparable
        } elseif ($val < $op2[$key]) {
            return -1;
        } elseif ($val > $op2[$key]) {
            return 1;
        }
    }
    return 0; // $op1 == $op2
}

Это действительно странное поведение: $ x меньше, чем $ y, и в то же время $ x больше, чем $ y (первый пример), и два массивасравнимо.

Я думаю, это потому, что php всегда сравнивает, начиная с одной определенной стороны знака '<'.Я имею в виду: для ($ x <$ y) php принимает $ x в качестве операнда 1, для ($ x> $ y) принимает $ y в качестве операнда 1. Хотя я не нашел ничего об этом поведении в документации.
Что вы думаете об этом?

Ответы [ 3 ]

1 голос
/ 26 июня 2011

Ваше предположение верно. Оператор > анализируется как

|   expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); }

Это в основном говорит, что X > Y эквивалентно not X < Y, что, конечно, неправильно, когда сравнение не коммутативно. Рассмотрите возможность сообщения об этом на bugs.php.net.

1 голос
/ 26 июня 2011

Я бы не сказал, что ошибка в $x > $y вместо $y < $x.

Конечно, если вы реализовали $x > $y таким образом, чтобы аргументы не обменивались позициями при передаче в функцию сравнения, вы бы решили эту конкретную проблему. Но вы получаете другой взамен.

Прямо сейчас у вас есть:

$x < $y <=> cmp($x, $y) == -1
$x > $y <=> cmp($y, $x) == -1

Поскольку первый ключ первого аргумента всегда сравнивается первым, оба условия выполняются, если reset($x) < $y[key($x)] и reset($y) < $x[key($y)].

Но рассмотрим другую реализацию, которая решит эту проблему:

$x < $y <=> cmp($x, $y) == -1
$x > $y <=> cmp($x, $y) == +1

Теперь < и > согласованы, когда порядок операндов фиксирован, но теперь мы получаем странное поведение, когда меняем местами операнды, потому что у нас все еще могут быть cmp($x, $y) == -1 и cmp($y, $x) == -1, что будет означать $x < $y и $y < $x оба будут истинными.

В итоге, единственным решением было бы установить функцию сравнения таким образом, чтобы ее поведение было антисимметричным, т. Е. Чтобы cmp($x, $y) == - cmp($y, $x), по крайней мере, в пределах набора элементов, которые, как утверждается, были сопоставимы.

0 голосов
/ 26 июня 2011

Я могу ошибаться, но я не думаю, что вы можете сравнивать массивы таким образом. Я всегда предполагал, что можно проверить равенство или неравенство, но не сравнивать величины с <и>.

Справочная страница по операторам массива , кажется, подтверждает это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...