sort() 唯一十六进制数数组(字符串类型):意外结果

sort() array of unique hexadecimal numbers (string-type): unexpected results

我需要一个已排序的十六进制数数组。 (在这种情况下,我将 128 位数字编码为 32 字节的十六进制字符串:这些是 IP 地址,转换为二进制 in_addr 形式,然后转换为十六进制:IPv4 地址已在前面加上“::”以给出一个地址空间。)使用 PHP 内置 "sort()" 函数排序在某些值上产生意外结果:

$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 弱类型执行的 "feature"?

我想两者兼而有之。问题是 PHP 在比较包含数值的字符串时过于友好。引用 the docs:

If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically.

现在考虑一下:

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 排序函数应该始终使用比较字符串,无论其中是否有数值。