我绞尽脑汁想解决这个难题。
PHP默认的sort
函数不能提供解决方案,但使用usort
也不容易。
这就是我想解决的问题。我按照这个顺序创建了一个数组:
$data = array( '_', '@', ...range(-10, 10), ...range('A', 'Z'), ...range('a', 'z') )
现在我想使用usort
对这个数组进行排序,这样:
negative
数字先出现,uppercase
字母_
和@
字符如下lowercase
字母如下- 最后
positive
数字结束订单
有点像:
/*
array(
"-10",
"-9",...
"A",
"B",...
"_",
"@", // @ may come first
"a",
"b",...
"1",
"2"...
) */
有什么方法可以解决这个问题吗?
我尝试了什么?
usort($data, function($a,$b) {
if( is_numeric($a) && (int)$a < 0 ) return -1; // take negative number to start
else {
if( !is_numeric($a) ) {
if( is_numeric($b) && (int)$b > 0 ) return -1;
else return $b < $a ? 1 : 0;
} else return 1; // take positive number to end
}
});
2条答案
按热度按时间cczfrluj1#
把它看作是一个等级制度。你有5个不重叠的“类”要排序:负数、大写、符号、小写、正数。因此,首先确定类排序,如果两个项的类相同,则比较它们的值。
旁白:类可以作为替代名称空间来包含相关的函数和变量,这样你就可以比完全内联或在本地/全局名称空间中转储东西更好地框出逻辑。
输出:
yks3o0rb2#
也许使用正则表达式对于一些开发人员来说会更难阅读/维护,我没有费心比较性能,但它确实提供了一些很好的代码简洁性。在正则表达式模式中对一系列可选的捕获组进行排序。正则表达式引擎将尝试满足最早出现的子模式,而剩余的捕获组甚至不会在matches数组(
$m[]
)中表示。然后,因为PHP在比较实际数据之前会先按数组的计数排序,所以$m
中元素最少的条目将首先按array_multisort()
排序。当然,这可以通过使用u
模式修饰符来增强以尊重多字节字符串。代码:(Demo)
更直观和易于扩展/维护的是使用具有速记三进制和宇宙飞船操作符比较的回退比较,直到适合常规排序。
代码:(Demo)(或Demo)
或者,如果性能是一个问题,通过准备计算数组来减少所需函数调用的总数,然后调用
array_multisort()
。(Demo)相关: