排序数组 - 数字,特殊字符,字母

时间:2013-07-04 15:27:58

标签: php sorting

我有数组,特殊字符和字母。我怎么能先把它挖走,然后是特殊的字符和字母。

$c64 = str_split(
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
);

我尝试这样做

array_multisort($l64, SORT_DESC);

但它会返回特殊的字符,数字和字母

2 个答案:

答案 0 :(得分:4)

这种事情可以非常“聪明”的方式实施,所以我无法抗拒:

$c64 = str_split(
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
);

$sortValue = function($char) {
    return !ctype_digit($char) << 9 | !ctype_punct($char) << 8 | ord($char);
}

$sortFunction = function($x, $y) use ($sortValue) {
    return $sortValue($x) - $sortValue($y);
};

usort($c64, $sortFunction);

<强> See it in action

工作原理

我正在利用ord返回字符的序数值这一事实,这是普通sort用于对输入进行排序以及约束的情况到[0,255]范围 - 即它的值不超过8位。

这段代码正在做的是获取ord的返回值(记住:这是默认的sort的工作原理)并用两个额外的信息来增加它:MSB表示“是这个字符一个数字?“并且LSB代表“这个字符不是标点符号吗?”。

这些位与序数值进行“或”运算,产生10位数量,如下所示:

Bit#    10  9  8  7  6  5  4  3  2  1  0
         ^  ^  ^                       ^
         |  |  \-----------+-----------/   
         |  |              \------------- ord
         |  \---------------------------- "not punctuation" bit
         \------------------------------- "not digit" bit

将这些值视为整数时会发生什么?显然,与非数字相对应的值将大于其他任何数字,并且与非标点符号相对应的类似值将大于字母等。

因此,通过使用$x - $y的结果来确定哪个项目更大,我们实际上将数字视为小于其他所有数字并且标点符号大于数字但小于非数字。这使得sort先将数字放入数字,然后是标点符号,然后在进行升序排序时将其他所有内容放入其中。

最后,ord的值参与比较是非常重要的:对于同一类中的元素(例如数字),我们希望它们的排序顺序与普通{{ 1}}会产生。

答案 1 :(得分:0)

usort($c64, function($a, $b){
    $aord = (is_numeric($a)) ? $a : ord($a);
    $bord = (is_numeric($b)) ? $b : ord($b);
    if ($aord == $bord) return 0;
    return ($aord < $bord) ? -1 : 1;
});