sort () массив уникальных шестнадцатеричных чисел (строковый тип): неожиданные результаты

0

Мне нужен отсортированный массив шестнадцатеричных чисел. (В этом случае у меня есть 128-битные числа, закодированные как 32-байтные шестнадцатеричные строки: это IP-адреса, преобразованные в двоичную форму in_addr, а затем преобразованные в шестнадцатеричные: адреса IPv4 были добавлены с "::", чтобы дать один адрес -пространство.) Сортировка с использованием встроенной функции sort() PHP дает неожиданные результаты для некоторых значений:

$test=array();
$test[]="00000000000000000000000005275087";
$test[]="00000000000000000000000005275104";
$test[]="00000000000000000000000005274E65";
$test[]="00000000000000000000000005274F32";
$test[]="0000000000000000000000000527501C";
\sort($test);
var_dump($test);

array(5) {
  [0]=> string(32) "00000000000000000000000005275087"
  [1]=> string(32) "00000000000000000000000005275104"
  [2]=> string(32) "00000000000000000000000005274E65"
  [3]=> string(32) "00000000000000000000000005274F32"
  [4]=> string(32) "0000000000000000000000000527501C"
}

Я думаю, что проблема должна быть где-то внутри функции sort(), возможно, вызвана неявным преобразованием типа (применяется непоследовательно внутри массива). Однако в качестве доказательства против идеи о том, что некоторые отдельные элементы массива сортируются как целые числа или числа с плавающей запятой, а другие сортируются как строки (чтобы я мог ожидать, что результаты будут стабильными, хотя все равно из строкового сортировочного порядка); Я считаю, что переупорядочение исходных элементов массива дает разные результаты, а также введение повторяющихся записей может вызвать функцию sort() для получения правильных результатов.

Пожалуйста, объясните это явление более полно и предложите несколько элегантных способов обойти эту проблему! Является ли это ошибкой в PHP или "особенностью" слабого применения PHP?

Теги:
string
arrays
sorting
hex

1 ответ

2
Лучший ответ

Похоже, это немного. Проблема в том, что PHP слишком дружелюбен при сравнении строк, содержащих числовые значения. Цитирование документов:

Если вы сравниваете число со строкой или сравниваете числовые строки, то каждая строка преобразуется в число, а сравнение выполняется численно.

Теперь рассмотрим следующее:

var_dump("5275104" < "5274E65"); // bool(true)
var_dump("5274E65" < "5274F32"); // bool(true)
var_dump("5275104" < "5274F32"); // bool(false) - WHAT?

В первом сравнении оба значения представляют собой числовые строки: первое очевидно, второе - из-за части E Их сравнивают как числа, как сказано в документах.

Во втором сравнении, однако, второй операнд не может быть полностью превращен в число, а значения теперь сравниваются как строки, поэтому он по существу 'E' < 'F'. Это та же ситуация в третьем сравнении (строки обрабатываются).


К счастью, это легко исправить:

\sort($test, SORT_STRING);

Флаг говорит PHP, что функция сортировки всегда должна использовать строки сравнения независимо от того, существуют ли в них числовые значения.

  • 0
    Спасибо. Теперь я буду использовать флаги SORT_ во всех моих операциях сортировки!
  • 0
    Да, это часто необходимо - и не только для удобства чтения. ) Я добавил объяснение.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню