
本文详细探讨了如何使用 php 的 `usort` 函数,在依据一个预设的参考数组对多维数组进行自定义排序时,正确处理那些未包含在参考数组中的元素。通过分析原始代码的不足,文章提出了一种健壮的解决方案,即为未匹配项分配一个极大的排序权重(如 `php_int_max`),从而确保它们被统一放置在排序结果的末尾,并提供了详细的代码示例和注意事项。
在 PHP 中,usort() 函数允许开发者使用自定义的比较函数对数组进行排序。这个比较函数(或称为回调函数)接收两个参数(通常是数组中的两个元素),并根据它们之间所需的相对顺序返回一个整数:
当我们需要根据一个预定义的顺序(例如一个字符串数组)来对另一个复杂数组进行排序时,usort() 是一个非常强大的工具。然而,一个常见的挑战是,当被排序的数组中包含一些元素,而这些元素并未出现在我们预定义的参考顺序中时,如何正确处理它们。通常,我们希望这些未匹配的元素被统一放置在排序结果的末尾。
假设我们有一个多维数组 $itemsToSort,需要根据另一个参考数组 $sortOrder 对其进行排序。$itemsToSort 中的每个子项的第一个元素($item[0])将用于与 $sortOrder 进行匹配。目标是让 $sortOrder 中定义的元素按其在 $sortOrder 中的顺序排列,而未在 $sortOrder 中定义的元素则被放置到数组的末尾。
一个常见的错误实现方式可能如下:
立即学习“PHP免费学习笔记(深入)”;
usort($itemsToSort, function($a, $b) use ($sortOrder){
$valA = array_search($a[0], $sortOrder);
$valB = array_search($b[0], $sortOrder);
if ($valA === false) // 如果 A 未找到
return -1; // 尝试将 A 放在 B 之前
if ($valB === false) // 如果 B 未找到(此时 A 必然已找到)
return 0; // 认为 A 和 B 顺序不变
// 如果 A 和 B 都找到,则按其在 $sortOrder 中的索引比较
if ($valA > $valB)
return 1;
if ($valA < $valB)
return -1;
return 0;
});上述代码存在逻辑缺陷:
这些逻辑错误导致当参考数组中只指定了少量值时,排序结果无法达到预期。
要解决这个问题,我们可以为那些未在 $sortOrder 中找到的元素分配一个“虚拟”的、极大的排序权重。这样,在比较时,这些具有极大权重的元素自然会排在所有具有正常(较小)权重的元素之后。PHP 提供了一个常量 PHP_INT_MAX,它代表了 PHP 能处理的最大整数值,非常适合作为这种“极大权重”的代表。
以下是使用 PHP_INT_MAX 策略的改进 usort 回调函数:
<?php
// 待排序的多维数组
$itemsToSort = [
['itemC', 'dataC'],
['itemA', 'dataA'],
['itemX', 'dataX'], // 未在 $sortOrder 中
['itemB', 'dataB'],
['itemY', 'dataY'], // 未在 $sortOrder 中
['itemD', 'dataD'],
['itemA', 'dataA_duplicate'], // 重复项
];
// 定义排序顺序的参考数组
$sortOrder = ['itemA', 'itemB', 'itemC'];
echo "原始数组:\n";
print_r($itemsToSort);
usort($itemsToSort, function($a, $b) use ($sortOrder){
// 获取 $a[0] 在 $sortOrder 中的索引,如果未找到则为 false
$rankA = array_search($a[0], $sortOrder);
// 获取 $b[0] 在 $sortOrder 中的索引,如果未找到则为 false
$rankB = array_search($b[0], $sortOrder);
// 如果未找到,将其排序权重设置为 PHP_INT_MAX,确保其排在所有已找到项之后
$rankA = ($rankA === false) ? PHP_INT_MAX : $rankA;
$rankB = ($rankB === false) ? PHP_INT_MAX : $rankB;
// 比较两个元素的最终排序权重
if ($rankA > $rankB) {
return 1; // A 排在 B 之后
}
if ($rankA < $rankB) {
return -1; // A 排在 B 之前
}
return 0; // 权重相等,保持原有相对顺序(或认为相等)
});
echo "\n排序后的数组:\n";
print_r($itemsToSort);
?>原始数组:
Array
(
[0] => Array
(
[0] => itemC
[1] => dataC
)
[1] => Array
(
[0] => itemA
[1] => dataA
)
[2] => Array
(
[0] => itemX
[1] => dataX
)
[3] => Array
(
[0] => itemB
[1] => dataB
)
[4] => Array
(
[0] => itemY
[1] => dataY
)
[5] => Array
(
[0] => itemD
[1] => dataD
)
[6] => Array
(
[0] => itemA
[1] => dataA_duplicate
)
)
排序后的数组:
Array
(
[0] => Array
(
[0] => itemA
[1] => dataA
)
[1] => Array
(
[0] => itemA
[1] => dataA_duplicate
)
[2] => Array
(
[0] => itemB
[1] => dataB
)
[3] => Array
(
[0] => itemC
[1] => dataC
)
[4] => Array
(
[0] => itemX
[1] => dataX
)
[5] => Array
(
[0] => itemY
[1] => dataY
)
[6] => Array
(
[0] => itemD
[1] => dataD
)
)从结果可以看出,itemA、itemB、itemC 按照 $sortOrder 的顺序排列,
以上就是PHP usort 自定义排序:将未匹配项高效置于数组末尾的策略的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号