[英]Sort By Alphabet then Numbers Laravel Collection
我正在寻找一种对集合进行排序的方法,即以字母开头的名称值位于顶部,然后名称值以数字开头。 例如:
$collection = collect([
['name' => 'b', 'symbol' => '#'],
['name' => '2a', 'symbol' => '$'],
['name' => '1', 'symbol' => '@'],
['name' => 'a', 'symbol' => '%']
]);
上面的集合应该是这样排序的:
[
[
"name" => "a",
"symbol" => "%",
],
[
"name" => "b",
"symbol" => "#",
],
[
"name" => "1",
"symbol" => "@",
],
[
"name" => "2a",
"symbol" => "$",
],
]
但这是我使用sortBy
方法对其进行排序时得到的:
$collection->sortBy('name')->values()->all();
[
[
"name" => "1",
"symbol" => "@",
],
[
"name" => "2a",
"symbol" => "$",
],
[
"name" => "a",
"symbol" => "%",
],
[
"name" => "b",
"symbol" => "#",
],
]
知道如何对这个集合进行排序,以便以字母开头的名称排在第一位吗?
您需要定义自己的自定义比较器 function 以使用 sort 对这些集合对象进行sort
。
通过检查它们都是字母来比较两个名称。 如果两者都是字母,则使用strcasecmp
进行通常的字符串比较就足够了。 如果它们中的任何一个是字母表,则通过返回值-1
将它们推到更高的等级,这意味着按排序顺序放置在上面。 如果两者都是数字或字母数字,请再次使用strcasecmp
。
<?php
$collection = collect([
['name' => 'b', 'symbol' => '#'],
['name' => '2a', 'symbol' => '$'],
['name' => '1', 'symbol' => '@'],
['name' => 'a', 'symbol' => '%']
]);
$collection = $collection->sort(function($a,$b){
$a_is_alphabet = preg_match('/^[a-zA-Z]+$/', $a['name']) === 1;
$b_is_alphabet = preg_match('/^[a-zA-Z]+$/', $b['name']) === 1;
if($a_is_alphabet && $b_is_alphabet){
return strcasecmp($a['name'], $b['name']);
}elseif($a_is_alphabet){
return -1;
}elseif($b_is_alphabet){
return 1;
}
return strcasecmp($a['name'], $b['name']);
});
您希望纯字母名称值具有最高优先级,然后我假设自然排序,例如a2
在a10
之前。 只需在sort()
方法调用的自定义回调中编写两条规则。
对 ASC 进行排序时,错误评估在真实评估之前排序,因此只需在 $ $a
元素之前写入$b
元素即可对 DESC 进行排序。 要在第一次比较中打破任何关系,请调用strnatcmp()
。
Laravel 早在 2019 年就采用了箭头 function 语法。
代码:(基本 PHP 演示)
$collection->sort(fn($a, $b) =>
(ctype_alpha($b['name']) <=> ctype_alpha($a['name']))
?: strnatcmp($a['name'], $b['name'])
);
如果您更具体地说只想检查第一个字符是否为字母,则可以使用$a['name'][0]
和$b['name'][0]
。 如果字符串可能有一个多字节的第一个字符,那么正则表达式方法可能是最好的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.