16

I have this array

Array
(
    [0] => Array
        (
            [brand] => blah blah
            [location] => blah blah
            [address] => blah blah
            [city] => blah blah
            [state] => CA
            [zip] => 90210
            [country] => USA
            [phone] => 555-1212
            [long] => -111
            [lat] => 34
            [distance] => 3.08
        )
    [1] => Array
        (
            [brand] => blah blah
            [location] => blah blah
            [address] => blah blah
            [city] => blah blah
            [state] => CA
            [zip] => 90210
            [country] => USA
            [phone] => 555-1212
            [long] => -111
            [lat] => 34
            [distance] => 5
        )
.
.
.

}

I want to be able to sort the arrays in the hash by distance.

1
  • array_multisort is backwards: It sorts a column array. (In fact, it sorts multiple independent arrays representing columns.) This is almost never what you want: Either transpose your array, or use something useful like usort. Commented Mar 14, 2011 at 23:48

6 Answers 6

25

You need to extract all the distances first, then pass both the distance and the data to the function. As shown in example 3 in the array_multisort documentation.

foreach ($data as $key => $row) {
    $distance[$key] = $row['distance'];
}

array_multisort($distance, SORT_ASC, $data);

This assumes you want the shortest distances first, otherwise change the SORT_ASC to SORT_DESC

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

Comments

16

If you want to avoid the looping you can use the array_column function to achieve your target. For Example,

You want to sort below array with distance sort

$arr = array( 
  0 => array( 'lat' => 34, 'distance' => 332.08 ),
  1 => array( 'lat' => 34, 'distance' => 5 ),
  2 => array( 'lat' => 34, 'distance' => 34 )
);

Using below single line your array will be sort by distance

array_multisort( array_column( $arr, 'distance' ), SORT_ASC, SORT_NUMERIC, $arr );

Now, $arr contain with sorted array by distance

Comments

4

The advantage to calling usort() instead of array_multisort(), is that you don't need to pre-iterate the input array to generate an array of columnar data.

The following one-liner will use PHP7.4's arrow function syntax with PHP7's "spaceship operator" / "three-way comparison operator" to sort the input array (by reference) based on the distance column values.

With $a on the left side of <=> and $b on the right side, ascending order is used. To achieve descending sorting, write $b['distance'] <=> $a['distance'].

Code:

usort($array, fn($a, $b) => $a['distance'] <=> $b['distance']);

var_export($array);

To break ties while sorting, you can declare multiple values to sort on via arrays of values.

The following will sort by:

  1. distance ASC then
  2. country DESC then
  3. state ASC then
  4. city ASC

Code:

usort(
    $array,
    fn($a, $b) =>
        [$a['distance'], $b['country'], $a['state'], $a['city']]
        <=>
        [$b['distance'], $a['country'], $b['state'], $b['city']]
);

Comments

2

Use can use usort;

function cmpDistance($a, $b) {
    return ($a['distance'] - $b['distance']);
}

usort($array, "cmpDistance");

8 Comments

The reason many compare functions return positive/negative number instead of explicitly -1 and 1 is to make functions like this simpler. The body of the function can just be return $a['distance'] - $b['distance']
why do I get a "Fatal error: Cannot redeclare cmp()"? Im confused
@dst11, just rename the function name to some other name, you probably already have it defined somewhere.
weird, it is ALMOST sorted out... hahaha for some reason, some entries are still unsorted. Could it be related that the distance is of type double? im not understanding this.
@dst11, Are the "distance" fields always valid numbers? You could try using return (floatval($a['distance']) - floatval($b['distance']));.
|
1

This code helps to sort the multidimensional array using array_multisort()

  $param_dt = array();
  foreach ($data_set as $key => $row) {
     if(isset($row['params']['priority']))
     {
       $param_dt[$key] = $row['params']['priority'];
     }
     else
     {
        $param_dt[$key] = -2; // if priority key is not set for this array - it first out
     }
    }

  array_multisort($param_dt, SORT_ASC,SORT_NUMERIC, $data_set); 

Now $data_set has the sorted list of elements.

Comments

1

We have an array of rows, but array_multisort() requires an array of columns, so we use the below code to obtain the columns, then perform the sorting.

// as of PHP 5.5.0 you can use array_column() instead of the above code
$brand= array_column($data, 'brand');
$city= array_column($data, 'city');

// Sort the data with volume descending, edition ascending
// Add $data as the last parameter, to sort by the common key
array_multisort($brand, SORT_DESC, $city, SORT_ASC, $data);

Comments

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.