0

I have this array of plans:

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
    )

)

I want them to be grouped by city like:

Tier 1 - LA

Tier 2 - LA

Tier 3 - LA

Tier 1 - NYC

Tier 2 - NYC

Tier 3 - NYC

Tier 1 - SF

Tier 2 - SF

Tier 3 - SF

I tried to use array_multisort() but it displays all Tier 1 first then Tier 2 and then Tier 3.

Currently, I'm doing 3 foreach loops to group them into 3 cities but it's not flexible and I think it's too long. What could be the quickest/easiest way to achieve this? Thanks!

1 Answer 1

1

You can use usort, using a sort function which extracts the city name out of the plan_name value using explode. If the city names are the same, we extract the tier number so we can sort by that instead:

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);
    }
});

I haven't included the output as it is quite long but you can see it in this demo on 3v4l.org

This is an alternate version which use preg_match to extract the city and tier from each 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

Sign up to request clarification or add additional context in comments.

1 Comment

@jeepers_creepers I've updated my answer with a couple of solutions that will also sort on the tier number

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.