uksort(array &$array, callable $callback): bool函数对数组的键进行排序。$callback是用户自定义的比较函数,接受两个键名作为参数,返回小于、等于或大于零的值,决定排序顺序。
示例代码:
$array = [
'apple' => 1,
'banana' => 2,
'cherry' => 3,
];
uksort($array, function($a, $b) {
return strcmp($a, $b);
});
print_r($array);
输出:
Array
(
[apple] => 1
[banana] => 2
[cherry] => 3
)
当键经过某种预处理或映射后,不同的原始键可能被认为是“相同键”,这时候比较函数可能频繁且重复地被调用,影响性能。例如:
$array = [
'a_1' => 10,
'a_2' => 20,
'b_1' => 30,
];
uksort($array, function($key1, $key2) {
// 只比较下划线前的部分
$part1 = explode('_', $key1)[0];
$part2 = explode('_', $key2)[0];
return strcmp($part1, $part2);
});
此时,'a_1'和'a_2'会被视为“相同键”,比较函数可能多次对它们进行比较。对于大型数组,这种重复会显著降低效率。
避免重复排序,关键是减少比较函数中对相同“逻辑键”的重复计算,甚至避免对等价键的多余比较。常用的做法有:
缓存映射结果:比较函数内部使用静态缓存,避免重复计算键的映射值。
先对键进行预处理和去重:先生成一个映射表,对键进行归类,排序时直接用映射结果比较。
使用辅助数组排序:用映射值作为辅助键,先生成一组映射值,再使用array_multisort()或其他排序函数避免重复调用。
$array = [
'a_1' => 10,
'a_2' => 20,
'b_1' => 30,
'b_2' => 40,
'c_1' => 50,
];
uksort($array, function($key1, $key2) {
static $cache = [];
if (!isset($cache[$key1])) {
$cache[$key1] = explode('_', $key1)[0];
}
if (!isset($cache[$key2])) {
$cache[$key2] = explode('_', $key2)[0];
}
return strcmp($cache[$key1], $cache[$key2]);
});
print_r($array);
这样,explode('_', $key)操作仅进行一次,避免重复计算,提升性能。
$array = [
'a_1' => 10,
'a_2' => 20,
'b_1' => 30,
'b_2' => 40,
'c_1' => 50,
];
// 生成映射键数组
$mappedKeys = [];
foreach (array_keys($array) as $key) {
$mappedKeys[$key] = explode('_', $key)[0];
}
// 按映射键排序键名
uasort($mappedKeys, function($a, $b) {
return strcmp($a, $b);
});
// 根据排序好的映射键重建主数组
$newArray = [];
foreach ($mappedKeys as $originalKey => $_) {
$newArray[$originalKey] = $array[$originalKey];
}
print_r($newArray);
该方案避免了在uksort中多次调用比较函数,适合映射规则复杂时使用。
使用uksort()时,比较函数会多次被调用,尤其当键需要转换或归类后相等的情况,容易出现重复计算。
通过在比较函数内使用缓存,或者事先对键进行映射排序,能有效避免重复排序,提升性能和代码清晰度。
选择哪种方案取决于数组大小、映射规则复杂度及性能需求。
掌握以上技巧后,你可以更灵活高效地使用uksort()进行复杂键排序。