You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PHP的usort按指定规则排序混合类型数组?

自定义数组排序问题解决

我一直在想办法解决这个排序难题,PHP默认的sort()函数满足不了需求,用usort()实现起来也没那么容易。我创建了这样一个数组:

$data = array( '_', '@', ...range(-10, 10), ...range('A', 'Z'), ...range('a', 'z') );

我希望用usort()对这个数组排序,规则是:

  • 负数排在最前面
  • 大写字母紧随其后
  • _、@这类符号排在大写字母之后
  • 小写字母接着排序
  • 正数排在最后

预期的排序结果如下:

/*
array(
  "-10",
  "-9",...

  "A",
  "B",...

  "_",
  "@", // @的顺序可能在前

  "a",
  "b",...

  "1",
  "2"...
) */

我尝试了下面的代码,但效果不对:

usort($data, function($a,$b) {
    if( is_numeric($a) && (int)$a < 0 ) return -1; // 把负数移到前面
    else {
        if( !is_numeric($a) ) {
            if( is_numeric($b) && (int)$b > 0 ) return -1;
            else return $b < $a ? 1 : 0;
        } else return 1; // 把正数移到最后
    }
});

请问有没有可行的解决办法?


可行的实现方案

要实现这个自定义排序,核心是给每个元素分配优先级分组权重,先按分组排序,组内再按元素自身规则排序。

实现代码

usort($data, function($a, $b) {
    // 给不同类型元素分配分组权重,权重越小排序越靠前
    $getGroup = function($item) {
        if (is_numeric($item)) {
            $num = (int)$item;
            return $num < 0 ? 0 : 4;
        } elseif (ctype_upper($item)) {
            return 1;
        } elseif (ctype_lower($item)) {
            return 3;
        } else {
            // 匹配_、@这类非数字非字母的符号
            return 2;
        }
    };

    $groupA = $getGroup($a);
    $groupB = $getGroup($b);

    // 先按分组权重排序
    if ($groupA !== $groupB) {
        return $groupA - $groupB;
    }

    // 同组内按元素自身规则排序
    if (is_numeric($a) && is_numeric($b)) {
        // 数字按数值大小排序
        return (int)$a - (int)$b;
    }
    // 字母、符号按自然字典序排序
    return strnatcmp($a, $b);
});

代码说明

  1. 分组权重逻辑:通过闭包$getGroup给每个元素分配对应权重,确保整体排序层级符合要求。
  2. 分组优先排序:先比较两个元素的分组权重,权重小的元素直接排在前面。
  3. 同组内排序:
    • 数字组按数值大小排序(负数从小到大,正数从小到大)
    • 字母和符号用strnatcmp实现自然字典序排序,符合常规排序预期

内容的提问来源于stack exchange,提问作者Uchenna Ajah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:45:20