繁体   English   中英

按字母排序,然后按数字排序 Laravel 集合

[英]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']);
});

您希望纯字母名称值具有最高优先级,然后我假设自然排序,例如a2a10之前。 只需在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM