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

时间:2015-01-07 09:29:03

标签: php arrays string sorting hex

我需要一个十六进制数字的排序数组。 (在这种情况下,我将128位数字编码为32字节十六进制字符串:这些是IP地址,转换为二进制in_addr形式,然后转换为十六进制:IPv4地址已添加到" ::&#34 ;给出一个地址空间。)使用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的弱类型执行?

1 个答案:

答案 0 :(得分:2)

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

  

如果您将数字与字符串进行比较或比较涉及   数字字符串,然后每个字符串转换为一个数字和   比较用数字表示。

现在考虑一下:

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,排序函数应始终使用比较字符串,而不管它们中是否有数值。