按特定字符串按字母顺序对数组进行排序

时间:2019-02-20 05:29:21

标签: php arrays sorting

我有以下一系列计划:

Array
(
[0] => Array
    (
        [plan_id] => corporate-base
        [plan_name] => Tier 1 - NYC
    )

[1] => Array
    (
        [plan_id] => corporate-la-base
        [plan_name] => Tier 1 - LA
    )

[2] => Array
    (
        [plan_id] => corporate-sf-base
        [plan_name] => Tier 1 - SF
    )

[3] => Array
    (
        [plan_id] => corporate-core
        [plan_name] => Tier 2 - NYC
    )

[4] => Array
    (
        [plan_id] => corporate-la-core
        [plan_name] => Tier 2 - LA
    )

[5] => Array
    (
        [plan_id] => corporate-sf-core
        [plan_name] => Tier 2 - SF
    )

[6] => Array
    (
        [plan_id] => corporate-la-unlimited
        [plan_name] => Tier 3 - LA
    )

[7] => Array
    (
        [plan_id] => corporate-sf-unlimited
        [plan_name] => Tier 3 - SF
    )

[8] => Array
    (
        [plan_id] => corporate-unlimited
        [plan_name] => Tier 3 - NYC
    )

)

我希望它们按城市分组:

  

第1层-洛杉矶

     

第2层-洛杉矶

     

第3层-洛杉矶

     

第1层-纽约

     

第2层-纽约

     

第3层-纽约

     

第1层-SF

     

第2层-SF

     

第3层-SF

我尝试使用array_multisort(),但它先显示所有第1层,然后显示第2层,然后显示第3层。

当前,我正在执行3个foreach循环以将它们分为3个城市,但这并不灵活,我认为时间太长。最快/最简单的方法是什么?谢谢!

1 个答案:

答案 0 :(得分:1)

您可以使用usort,并使用排序功能,该功能使用explodeplan_name值中提取城市名称。如果城市名称相同,我们将提取等级号,以便我们可以按其排序:

usort($array, function ($a, $b) {
    $city_a = explode('-', $a['plan_name'])[1];
    $city_b = explode('-', $b['plan_name'])[1];
    if ($city_a == $city_b) {
        // sort by tier
        $tier_a = (int)explode(' ', $a['plan_name'])[1];
        $tier_b = (int)explode(' ', $b['plan_name'])[1];
        return $tier_a - $tier_b;
    }
    else {
        return strcmp($city_a, $city_b);
    }
});

我没有包含输出,因为它很长,但是您可以在此demo on 3v4l.org

中看到它

这是备用版本,使用preg_match从每个plan_name中提取城市和等级:

usort($array, function ($a, $b) {
    preg_match('/^Tier\s*(\d+)\s*-\s*(\w+)$/', $a['plan_name'], $matches_a);
    preg_match('/^Tier\s*(\d+)\s*-\s*(\w+)$/', $b['plan_name'], $matches_b);
    // are the cities the same?
    if ($matches_a[2] == $matches_b[2]) {
        // yes, sort by tier
        return $matches_a[1] - $matches_b[1];
    }
    else {
        // no, sort by city
        return strcmp($matches_a[2], $matches_b[2]);
    }
});

Demo on 3v4l.org