PHP ksort 意外行为

4
让我从头开始告诉你:我知道这个函数的排序标志。当我使用 SORT_STRING 时,它可以正常工作,但默认标志 SORT_REGULAR 的表现很奇怪,有时甚至无法正常工作。
考虑下面这样一个数组。
$arr = [
    '27a'   => 'foo',
    '27b'   => 'foo',
    '27c'   => 'foo',
    '27'    => 'foo',
];

当我尝试使用ksort进行排序时,它返回的数组似乎没有按照任何明显的逻辑排序。

ksort($arr);

print_r($arr);

// this prints
Array
(
    [27a] => foo
    [27] => foo
    [27b] => foo
    [27c] => foo
)

可以说,这些键既不是按数字顺序排列的,也不是按字母数字顺序排列的,也不是按自然顺序排列的。更奇怪的是,当我改变源数组的顺序时,它会产生不同的结果:

$arr = [
    '27a'   => 'foo',
    '27'    => 'foo',
    '27b'   => 'foo',
    '27c'   => 'foo',
];

ksort($arr);

print_r($arr);

// this prints
Array
(
    [27b] => foo
    [27c] => foo
    [27] => foo
    [27a] => foo
)

有人知道这背后的逻辑吗?这是一个bug还是我漏掉了什么?

编辑:感谢大家对我的问题感兴趣并回答。虽然它被标记为重复,但另一个问题没有提到更奇怪的部分:为什么改变源数组的顺序会改变结果?它应该在相同的输入集下给出相同的结果。 我们也讨论一下这个问题吧。


谢谢大家对我的问题感兴趣并给予回答。虽然它被标记为重复,但是另一个问题没有提到更奇怪的部分:为什么改变源数组的顺序会改变结果?它应该在相同的输入集的情况下给出相同的结果。我们是否也应该讨论这个问题? - Blameself
1个回答

4
发生这种情况的原因是它将像“27a”这样的键视为字符串,将像“27”这样的键视为整数,即使有引号也是如此。如果从27键中删除引号,则会看到相同的结果。
正如ksort页面所说:“警告:当对具有混合类型值的数组进行排序时要小心,因为sort()可能会产生不可预测的结果。”
这绝对是一种奇怪的行为 - 不幸的是,当您拥有看起来像整数的键(即使它们是字符串)时,产生预期结果的最佳方法是指定 SORT_STRING 这样的排序标志,以确保每次都获得预期的结果。

谢谢。我应该面对这个事实,即来自php.net/manual/en/function.sort.php的SORT_REGULAR定义根本不可靠:“SORT_REGULAR-正常比较项目(不更改类型)”。这让我错误地认为它不会将数字字符串作为整数处理。 - Blameself

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接