如何使用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); });
代码说明
- 分组权重逻辑:通过闭包
$getGroup给每个元素分配对应权重,确保整体排序层级符合要求。 - 分组优先排序:先比较两个元素的分组权重,权重小的元素直接排在前面。
- 同组内排序:
- 数字组按数值大小排序(负数从小到大,正数从小到大)
- 字母和符号用
strnatcmp实现自然字典序排序,符合常规排序预期
内容的提问来源于stack exchange,提问作者Uchenna Ajah
相关产品推荐
相关产品推荐

