Алгоритм сравнения массивов PHP
При попытке имитировать немного поведения PHP я наткнулся на это:
$a=array(0 => 1, 'test' => 2);
$b=array('test' => 3, 0 => 1);
var_dump($a==$b, $a>$b, $b>$a);
В соответствии с выходом var_dump
$b
больше, чем $a
. В руководстве по PHP есть Транскрипция сравнения стандартных массивов, в которой указано, что значения массивов сравниваются по одному и если ключ из первый массив отсутствует во втором массиве, массивы несравнимы. Все идет нормально. Но если я попробую это (изменение только в первом элементе $a
):
$a=array(0 => 2, 'test' => 2);
$b=array('test' => 3, 0 => 1);
var_dump($a==$b, $a>$b, $b>$a);
Все три результата сравнения false
. Это выглядит как "несравнимое" для меня (поскольку результат >
совпадает с результатом <
, тогда как массивы не являются ==
, что не имеет смысла), но это не соответствует транскрипции из PHP руководство. Оба ключа присутствуют в обоих массивах, и я ожидал бы, что $a
будет больше на этот раз, потому что содержимое ключа 0 больше в $a
(2 против 1).
Я попытался вникнуть в исходный код PHP и нашел zend_hash_compare() в zend_hash.c
, но код там, похоже, работает как описано в руководстве.
Что здесь происходит?
Ответы
Ответ 1
Казалось бы, цикл сравнения в случае > выполнен по правому массиву, а в случае < выполняется над левым массивом, т.е. всегда над якобы "меньшим" массивом. Порядок элементов значим, поскольку цикл foreach в коде транскрипции соответствует порядку массива.
Иными словами;
$a > $b петли над b и сначала обнаруживает "тест". 'test' больше в $b, поэтому $b больше и возвращает false.
$b > $a зацикливается на a и сначала находит "0". '0' больше в $a, поэтому $a больше и возвращает false.
Это действительно имеет смысл, тогда "большему" массиву разрешено содержать элементы, которые "меньший" массив не имеет и все еще больше, если все общие элементы больше.
Ответ 2
РЕДАКТИРОВАТЬ: Как показал Йоахим, речь идет о вызванном порядке. Чтобы украсть его слова:
"$ a > $b петли над b и сначала обнаруживает" тест "." test "больше в $b, поэтому $b больше и возвращает false. $b > $a перебирает a и сначала находит" 0 ". 0 'больше в $a, поэтому $a больше и возвращает false."
- Оригинальное сообщение -
Я не уверен на 100%, что я прав; Я этого раньше не видел, и только кратко посмотрел на него (по большому счету, на отличный вопрос!). В любом случае, похоже, что либо документация PHP неверна, либо это ошибка (в этом случае вы можете отправить ее), и вот почему:
в zend_hash_compare()
в zend_hash.c
, кажется, что есть какая-то путаница в отношении того, что ordered
(я смотрю на строку 1514
и 1552-1561
, что является моим лучшим предположением, где проблема без проведения большого тестирования).
Вот что я имею в виду; попробуйте следующее:
$a=array(0 => 2, 'test' => 2);
$b=array(0 => 1, 'test' => 3);
var_dump($a==$b, $a>$b, $b>$a);
Примечание. Я просто переключил порядок индексов, а $a>$b
возвращает true
. Также см. Это:
$x=array(0 => 2, 'test' => 2);
$y = $x;
$y[0] = 1; $y['test'] = 3;
var_dump($x==$y, $x>$y, $y>$x);
Обратите внимание, что $x>$y
возвращает true. Другими словами, PHP не просто соответствует ключам массива! Он заботится о порядке этих ключей в массивах! Вы можете предотвратить эту ситуацию, придумав "базовый" массив и "скопировав" его на новые переменные (в моем примере x/y) до изменения, или вы можете создать объект, если хотите.
Чтобы сказать все по-другому и, что еще более кратко, казалось бы, PHP не просто смотрит на ключевые значения, а на оба ключевых значения и порядок клавиш.
Опять же, я подчеркиваю, что я не знаю, было ли это ожидаемое поведение (кажется, что-то, что они должны были заметить в руководстве PHP, если это было), или ошибка/ошибка/etc (что кажется мне гораздо более вероятным). Но в любом случае, я нахожу, что его сначала сравнивают по количеству ключей (строки 1496-1501
in zend_hash.c
), а затем как по значению ключа, так и по порядку.
Ответ 3
Я думаю, что здесь сравнивается один за другим, поэтому $a[0]>$b[0]
, но $a['test']<$b['test']
.
Вы не можете сказать, какой массив больше.