3

Firstly, YES, this is a duplicate issue that's been asked 100 times on here, and I've read through many of the posts, but the examples given aren't working 100% for me and I can't figure out where I'm going wrong.

I want to sort an array like this by the 'distance' key, and I want the sort to be "expanded" across the entire array so it reorders all keys in the array. In essence, just like you'd get if you sorted a column in a spreadsheet and expanded the sort across all columns.

Here's the sample array:

$locations = array ( 
[phone] => Array ( 
    [0] => 555-123-1234 
    [1] => 555-456-4321 
    [2] => 555-789-1122 
    [3] => 555-321-1111 ) 
[address] => Array ( 
    [0] => 123 Main Street BigCity, NY 12345
    [1] => 456 Maple Street Somewhere, UT 87654
    [2] => 999 1st Ave MyTown, VA 23456
    [3] => 321 2nd Ave MyTown, VA 23456 ) 
[distance] => Array ( 
    [0] => 24.56
    [1] => 13.05
    [2] => 23.99
    [3] => 1.75 ) 
[name] => Array ( 
    [0] => First Location
    [1] => Second Location
    [2] => Third Location
    [3] => Fourth Location ) 
)

I'm trying to sort the array by 'distance', and I've tried using both the array_multisort() function and the usort() function ...but only "multisort" gives me nearly usable results by sorting the distances only and not sorting the entire array according to distance.

My function:

array_multisort($locations['distance'], SORT_NUMERIC);

I then run a "for" loop to traverse the array and spit out the values by key. The result is the distances are ordered but the Location names, addresses, etc. don't get reordered.

What am I missing here??

Thanks!!

0

2 Answers 2

3

Your array is arranged in columns, whereas array_multisort() when used in this way expects it to be arranged in rows.

It should be in the structure that you would get if you did:

$rows = array();
while ($row = $result->fetch_assoc()) $rows[] = $row;

...with a MySQLi result object.

You can reformat your existing array into this structure quite easily:

$locationsAsRows = array();
for ($i = 0; isset($locations['phone'][$i]); $i++) {
  $locationsAsRows[$i] = array (
    'phone' => $locations['phone'][$i],
    'address' => $locations['address'][$i],
    'distance' => $locations['distance'][$i],
    'name' => $locations['name'][$i]
  );
}
var_dump($locationsAsRows);

Now, when you do:

array_multisort($locations['distance'], SORT_NUMERIC, $locationsAsRows);
var_dump($locationsAsRows);

...you can see that the data has been sorted. Note that not only did I pass the column data you wanted to sort by, I also passed the whole "row formatted" $locationsAsRows array as the last argument. This is passed by reference, so $locationsAsRows itself will be the sorted data after you have called array_multisort().

Now let's say that two of the distance values are the same - we need to supply a second priority search column. So next, we could sort by address, and we can do that like so:

array_multisort($locations['distance'], SORT_NUMERIC, $locations['address'], SORT_ASC, $locationsAsRows);

See it working and have a play around with it...

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

4 Comments

Thanks for the great explanation and example! I guess part of what I wasn't understanding was HOW these functions were looking at the arrays. However, in using your example I had to sort ALL columns that I wanted matched by row. I'm not sure why that is, but it works if I add all rows in the multisort function. Any thoughts on why that might be?
array_multisort() can be used in many ways, but with this option is behaves roughly like an order by clause in an SQL query. And in SQL, you are always dealing with rows. You have to pass the datasets to be sorted by (the columns) so it knows how to sort the data, then you pass the whole dataset as the last argument so that it can be sorted according to these rules. So it is like SELECT phone, address, distance, name FROM locations ORDER BY distance
That is equivalent to SELECT phone, address, distance, name FROM locations ORDER BY distance, address, name, phone - each additional pair of $col, SORT_CONST values before the full data set $locationsAsRows is like another level to the ORDER BY clause. So the $locations['phone'], SORT_ASC will probably never be reached unless two records have the exact same values for distance, address and name.
That makes total sense when you put it in SQL speak like that, but I had to do it this way to get all rows ordered together: array_multisort($locations['distance'], SORT_NUMERIC, $locations['address'], SORT_ASC, $locations['name'], SORT_ASC, $locations['phone'], SORT_ASC, $locationsAsRows); ....otherwise it only ordered the one column.
-1
array_multisort($locations['distance'],$locations['name'],$locations['address'],$locations['phone'],SORT_NUMERIC);

Maybe this will do the job?

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.