Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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!!

share|improve this question
add comment

2 Answers

up vote 3 down vote accepted

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...

share|improve this answer
    
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? –  gtr1971 Feb 21 '12 at 15:42
    
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 –  DaveRandom Feb 21 '12 at 17:26
    
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. –  DaveRandom Feb 22 '12 at 15:25
    
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. –  gtr1971 Feb 22 '12 at 15:27
add comment
array_multisort($locations['distance'],$locations['name'],$locations['address'],$locations['phone'],SORT_NUMERIC);

Maybe this will do the job?

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.