我正在开发一个类,它使PHP中的数组排序更容易,而且我一直在使用SORT_常量,但是行为或SORT_REGULAR
(默认排序类型)似乎根据顺序而不同您添加数组中的项目。而且,我无法看出为什么会出现这种情况的模式。
数组项目
$a = '0.3';
$b = '.5';
$c = '4';
$d = 'F';
$e = 'z';
$f = 4;
情景1:
sort(array($d, $e, $a, $f, $b, $c));
// Produces...
array(6) {
[0]=>
string(3) "0.3"
[1]=>
string(2) ".5"
[2]=>
string(1) "4"
[3]=>
string(1) "F"
[4]=>
string(1) "z"
[5]=>
int(4)
}
情景2:
sort(array($d, $e, $b, $f, $c, $a));
// Produces...
array(6) {
[0]=>
string(3) "0.3"
[1]=>
string(2) ".5"
[2]=>
string(1) "F"
[3]=>
string(1) "z"
[4]=>
int(4)
[5]=>
string(1) "4"
}
有什么想法吗?
答案 0 :(得分:2)
此行为是“预期的”(或至少已知),因为您对值(字符串和整数)使用不同的类型。请参阅sort()
功能手册。
警告强>
在对具有混合类型值的数组进行排序时要小心,因为sort()会产生不可预测的结果。
最有可能的是,在排序算法的某个时刻,它将两个值比较为整数而不是字符串。为了避免这种情况,不要尝试对不同类型的数组进行排序(如手册所述)。
答案 1 :(得分:2)
警告
排序具有混合类型值的数组时要小心,因为sort() 会产生不可预测的结果。
您应该使用其中一个SORT_ *常量。
这里有一些评论:
答案 2 :(得分:1)
<
类似。似乎SORT_REGULAR
遵循与<
运算符相同的规则(因此,>
运算符)。
在我自己的测试中,对于任何两个值$ v0和$ v1,以下断言确实通过了:
$pair = [$v0, $v1];
sort($pair);
assert($pair[0] < $pair[1]);
<
不是严格的弱序。不幸的是,<
混合使用字符串和整数具有循环行为,并且不具有传递性。因此,它不是Strict weak order
这可以通过以下断言显示,pass:
assert('3' < '10'); // Numeric comparison. 2 < 12.
assert('10' < '2 '); // Lexicographical comparison
// Circular:
assert('2 ' < '3'); // Lexicographical comparison
// Not transitive:
assert(!('3' < '2 ')); // Lexicographical comparison
// And just because it's interesting:
assert('2 ' < 3); // Numeric comparison. 2 < 3.
排序的想法是,在排序的项目列表中,如果$i < $j
,则!($sorted_items[$j] < $sorted_items[$i])
。
仅当<
是严格的总订单或严格的弱订单时才可以这样做。
<
会将字符串作为数字读取。以下规则似乎适用于<
:
(*)字符串&#39; 4&#39; &#34;看起来像&#34;数字4.字符串&#39; 4 x&#39;不是&#34;看起来像&#34;数字4,但(int)'4 x'
仍然评估为4。
此特定示例中的排序在PHP 7中实际上是一致的,而不是在PHP 5中*,可以看作here。
这并不意味着PHP 7可以免受这个问题的影响。在这个具体的例子中恰好可以。
比较各个值reveals:
hhvm-3.9.1 - 3.12.0,7.0.0 - 7.1.0alpha2
'0.3' < '.5'
'0.3' < '4'
'0.3' < 'F'
'0.3' < 'z'
'0.3' < 4
'.5' < '4'
'.5' < 'F'
'.5' < 'z'
'.5' < 4
'4' < 'F'
'4' < 'z'
'4' < 4
'F' < 'z'
'F' < 4
'z' < 4
5.5.0 - 5.6.23
'0.3' < '.5'
'0.3' < '4'
'0.3' < 'F'
'0.3' < 'z'
'0.3' < 4
'.5' < '4'
'.5' < 'F'
'.5' < 'z'
'.5' < 4
'4' < 'F'
'4' < 'z'
4 < '4'
'F' < 'z'
'F' < 4
'z' < 4
现在让我们删除无聊的位。
在PHP 7中:
'F' < 'z'
仍然存在。没有通告。因此,可能只有一种排序顺序:['0.3', '.5', '4', 'F', 'z', 4]
。在PHP 5中。*:
有多种方法可以使用这些结果构建圈子。
其中一个圈子是:'4' < 'F'
,'F' < 4
,4 < '4'
。
这意味着:在任何排序顺序中,至少有两个职位$i
和$j
与$i < $j
但$sorted[$j] < $sorted[$i]
。