amey1908
amey1908

Reputation: 157

Sort an array based on two other arrays

I have a total of three arrays

Array 1

array1 = Array( 
    [0] => Array(
        [name] => John 
        [city] => San Francisco 
        [state] => CA 
    ) 
    [1] => Array(
        [name] => Smith 
        [city] => Atlanta 
        [state] => GA 
    ) 
    [2] => Array(
        [name] => Peter 
        [city] => New York 
        [state] => NY 
    ) 
    [3] => Array(
        [name] => Mary 
        [city] => San Jose 
        [state] => CA 
    ) 
)

Array 2 (sorted on average age)

array2 = Array(
    [0] => CA 
    [1] => NY 
    [2] => GA
) 

Array 3 (sorted based on population)

array3 = Array(
    [0] => New York 
    [1] => San Francisco 
    [2] => Atlanta 
    [3] => San Jose
)

How do I sort array 1 based on array 2 first and then by array 3. I want the following output:

Sorted Array 1

Array
(
    [0] => Array
        (
            [name] => John
            [city] => San Francisco
            [state] => CA
        )

    [1] => Array
        (
            [name] => Mary
            [city] => San Jose
            [state] => CA
        )

    [2] => Array
        (
            [name] => Peter
            [city] => New York
            [state] => NY
        )

    [3] => Array
        (
            [name] => Smith
            [city] => Atlanta
            [state] => GA
        )

)

I tried using array_multisort for achieving this, but it's not working, e.g.

array_multisort($array2,$array3,$array1)

Any help is highly appreciated.

Upvotes: 1

Views: 177

Answers (2)

Daniel Miladinov
Daniel Miladinov

Reputation: 1592

Here's one way to sort $array1 by $array2 and $array3 to produce the results you want:

<?php

$array1 = array(
    array('name' => 'John',  'city' => 'San Francisco', 'state' => 'CA'),
    array('name' => 'Smith', 'city' => 'Atlanta',       'state' => 'GA'),
    array('name' => 'Peter', 'city' => 'New York',      'state' => 'NY'),
    array('name' => 'Mary',  'city' => 'San Jose',      'state' => 'CA'),
);

$array2 = array(
    'CA',
    'NY',
    'GA'
);

$array3 = array(
    'New York',
    'San Francisco',
    'Atlanta',
    'San Jose'
);

usort(
    $array1,
    function ($element1, $element2) use ($array2, $array3) {
        $state_sort_order = array_flip($array2);

        $element1_state_sort_order = $state_sort_order[$element1['state']];
        $element2_state_sort_order = $state_sort_order[$element2['state']];

        $state_sort_result = $element1_state_sort_order - $element2_state_sort_order;

        if ($state_sort_result === 0) {
            $city_sort_order = array_flip($array3);
            $element1_city_sort_order = $city_sort_order[$element1['city']];
            $element2_city_sort_order = $city_sort_order[$element2['city']];

            return $element1_city_sort_order - $element2_city_sort_order;
        } else {
            return $state_sort_result;
        }
    }
);

print_r($array1);

Again, usort seemed to be the choice with the most flexibility. There might be a way to figure out how to use array_multisort, but I couldn't tell based on the data you've given.

I use a function closure, capturing $array2 and $array3 from the outer scope to do the sorting. It defines a comparison function for usort to apply to elements of $array1 to determine sort order. In this function, $element1 and $element2 each receive the value of elements from $array1 to process for comparison, e.g 'Smith,Atlanta,GA', or 'Mary,San Jose,CA'.

For each element, I extract the city and state portions of the elements. If you flip $array2 and $array3, they become lookup tables for sort order when you index them by $city and $state, respectively.

The rest is just returning the difference between city sort orders if the state sort orders are equal, else just return the state sort orders.

Upvotes: 2

abegosum
abegosum

Reputation: 637

You'll want to use usort. You can define a user-defined function that compares the elements of array 1 with array 2 and 3 and use that callback in usort to perform the sort.

Upvotes: 1

Related Questions