Examples

In this example, after sorting, the first array will contain 0,
10, 100, 100. The second array will contain 4, 1, 2, 3. The
entries in the second array corresponding to the identical
entries in the first array (100 and 100) were sorted as well.

In this example, after sorting, the first array will transform to
"10", 100, 100, 11, "a" (it was sorted as strings in ascending
order). The second will contain 1, 3, "2", 2, 1 (sorted as numbers,
in descending order).

User Contributed Notes 56 notes

I came up with an easy way to sort database-style results. This does what example 3 does, except it takes care of creating those intermediate arrays for you before passing control on to array_multisort().

Advantage of function: - uses PHP's array_multisort function for sorting;- it prepares the arrays (needed by array_multisort) for you;- allows the sort criteria be passed as a separate array (It is possible to use sort order and flags.); - easy to set/overwrite the way strings are sorted (case insensitive instead of case sensitive, which is PHP's default way of sorting);- performs excellent

The explanation is :"In this example, [...] The second will contain 1, 3, "2", 2, 1 (sorted as numbers, in descending order). "This could be misunderstood cause a sort as numbers in descending order will be 1, 1, "2", 2, 3.

My proposal is as follows (in a best english should be great ^^) :"In this example, [...] The second will contain 1, 3, "2", 2, 1 (sorted as well as first one, except for values 3 and "2" sorted as numbers, in descending order). Because they are corresponding to the identical entries in the first array (100 and 100) which couldn't be sorted at first time."

I would like to report a kind of confusion that arose with the message

Warning: Call-time pass-by-reference has been deprecated; If you would like to pass it by reference, modify the declaration of array_multisort(). If you would like to enable call-time pass-by-reference, you can set allow_call_time_pass_reference to true in your INI file...

from a line like this:

array_multisort (&$keyarr, &$arr );// sort against this keys

This message is not easily switched off by changing the error reporting level because it's produced at parsinig time -- not execution time.

I think this message is misleading because the arguments are passed by reference ANYWAY in array_multisort.

Anybody encountering this message should know that nothing has to be done, except deleting the ampersands (&).I was tricked by this message because of couse I wanted to have the *sorted* array back. And couldn't find the ini file nor the declaration of array_multisort.I think in this description of array_multisort the call by reference should be listed in the definition.

When I was working on a search engine, that had to order the results in PHP by multiple arguments, I got stuck on the issue of multisort erasing your (numeral) indexes for a while. Sometimes, it is important to keep these indexes intact. In my case, the indexes were IDs and the values were a percentage of how relevant the object was, considering an earlier query.e.g: $searchResult = (23 => 0.3, 102 => 0.5, 11 => 0.5, 340 => 0.5, 10 => 0.9);

I wanted to use array_multisort to first sort DESC on the IDs, and then on the values DESC. i.e. I wanted to show the highest values first, but in case of two (or more) objects with the same value, the higher ID would be shown first.e.g: $searchResult = (10 => 0.9, 340 => 0.5, 102 => 0.5, 11 => 0.5, 23 => 0.3);

The easiest way to do this, I think, is:<?php// create a 2-deep array with the values and keys of $searchResult$array = array($searchResult,array_keys($searchResult) );// use multisort, first on the values, then on the keys. This will erase the indexes in the $searchResult arrayarray_multisort($array[0], SORT_DESC, $array[1], SORT_DESC);// get the ordered keys back in the $searchResult array$searchResult = array_combine($array[1], $array[0]); unset($array); //clear some memory?>

I was (as near everyone here :-) looking to sort 2-dimensional arrays by certain fields in the associative sub-arrays.What I didn't like about the documentation examples is that you need to loop through the input array to create sub arrays first, then use those in the function call.

"php a-t-the-r-a-t-e chir.ag" (http://www.php.net/manual/en/function.array-multisort.php#60401) wrote a quite cunning wrapper function, I rewrote it slightly, changing variable names and adding comments (for my sanity :-) mostly.One snag I found: the input array is passed to array_multisort as last argument, but the changed array is not the one that is returned. Passing it by reference fixed that. This seems to be caused by the whole thing sitting inside the call_user_func_array, as shown below.

Often, one may have a group of arrays which have parallel data that need to be kept associated with each other (e.g., the various attribute values of a group of elements might be stored in their own arrays). Using array_multisort as is, by specifying additional fields, it is possible, as in the documentation example cited below, that this association will be lost.

To take this example set of data from the documentation:<?php$ar1 = array("10", 100, 100, "a");$ar2 = array(1, 3, "2", 1);?>

The example goes on to sort it this way:<?phparray_multisort($ar1, $ar2);?>

In this case, although the "10" remains associated with the first '1' after being sorted, the "2" and '3' are reversed from their original order.

In order to sort by one field only (yet still have the other array(s) being correspondingly sorted), one can use array_keys (which makes an array out of the keys) to ensure that no further sub-sorting is performed. This works because array_keys is making an array for which no duplicates can exist (since keys will be unique), and thus, the subsequent fields will have no relevance as far as subsorting.

So, using the above data, we can perform this sort instead:<?php$ar3 = array_keys($ar1);array_multisort($ar1, $ar3, $ar2);?>

Since the manual doesn't specify so, I want to point out that the SORT_NUMERIC flag does also work correctly if the values are floating point numbers. Just don't forget to also add the respective SORT_ASC or SORT_DESC flag :)

Explanation:I took an existing example found above that shows how to sort an array by one of it's columns/fields.I just added: "+(rand(1,9)/10)" To randomly add .1 through .9 to their score to resolve the tie. (Obviously this specific example only works if you're sorting by an integer... so you may need to modify it to suit your needs.)

array_multisort works normally in php 5.3, but it forces arguments to be references.

It doesn't make differences for common array_multisort() usage, but makes "problems" for sorting variable number of arrays where call_user_func_array() function is involved.

So all sorting arrays have to be collected into new one as a references to array variables:

<?php$sortArgs = array();

for (...) { ...$sortArgs[] = &$valuesArray; ...}

call_user_func_array('array_multisort', $sortArgs);?>

This (requiring arguments to be a reference) is not actually a problem since source array will not be sorted otherwise.

Important note!Don't forget to destroy $valuesArray variable if you use it over each array_multisort() argument processing iteration.If you don't do it, all array_multisort() arguments will contain the same array:

And the last important thing :)Collect sorting arrays somewhere. PHP 5.3 will transfer reference into value (when $valuesArray is destroyed) and you will get "Parameter 1 to array_multisort() expected to be a reference, value given" warning again otherwise.

When sorting an array of (complex) objects, this function can give you a "Fatal error: Nesting level too deep" since it directly compares elements in later arrays if the elements in earlier ones compare equal. This can be worked around with the Flag-Parameter:<?php $sortKeys = array_map($extractKey, $lotsOfComplexObjects);array_multisort($sortKeys, $lotsOfComplexObjects, SORT_ASC, SORT_NUMERIC);?>I'm replacing an 'uasort()'-call which is significantly slower since it leads to a lot of calls to the comparison-function but most of the objects involved are recursive.

I didn't see this noted anywhere, so I figured I'd put in a little comment regarding arrays located inside classes. For instance:

class abc{ var $data;}

The following code does not act as expected:

$clsVar =& new abc();

foreach ($clsVar->data as $key => $row) { $position[$key] = $key; }

array_multisort($position, SORT_DESC, $clsVar->data);

While I realize this could much easily be acheived using ksort(), this is merely a much more simple example of this behaviour. The exerpt above comes from a much more complicated sort using multi-scripted arrays.

Anyway the only way I could find to get around the behaviour of multisort not sorting the referenced class-array was to make a copy of it as below:

} array_multisort($basename_i, SORT_ASC, $report_files_x);?>The above works but if you change the last time to :-<? array_multisort((array)$basename_i, SORT_ASC, (array)$report_files_x);?>...adding the (array) cast doesn't sort the main array ...

AMC_SORT_STRING_CASELESS to sort the strings case insensitively.
AMC_LOSE_ASSOCIATION (the default behaviour) to lose the associations for the array.
AMC_KEEP_ASSOCIATION to keep the associations for the array.

Other than that, these function work together JUST like array_multisort but sorts using column(s) without the need to first extract the columns into individual arrays.

Many thanks to “AlberT at SuperAlberT dot it” for his useful and elegant function. I have made some small alterations so it doesn’t use pass-by-reference as this throws up warnings in newer versions of php4.

I wanted to share with you a function that I created to make the array_multisort process much easier for myself... There was some interesting things that I encountered and I will post that in the comments.

I created this function so that all I have to do is tell it what column I want to sort through in a one level deep multidimensional array. You can Try this code in your browser to view the results

//$array: the array you want to sort//$by: the associative array name that is one level deep////example: name//$order: ASC or DESC//$type: num or str

$sortby = "sort$by"; //This sets up what you are sorting by

$firstval = current($array); //Pulls over the first array

$vals = array_keys($firstval); //Grabs the associate Arrays

foreach ($vals as $init){$keyname = "sort$init"; $$keyname = array();}//This was strange because I had problems adding//Multiple arrays into a variable variable//I got it to work by initializing the variable variables as arrays//Before I went any further

//This will create dynamic mini arrays so that I can perform//the array multisort with no problem//Notice the temp array... I had to do that because I //cannot assign additional array elements to a //varaiable variable

asort($test) will not let me specify which columns to sort ASC/DESC, NUMERIC/STRING etc.

I have data similar to what you specified. Now I want to sort $test by points DESC and name ASC. Here's my function that does it, based on suggestions on this page. It uses array_multisort (and hence acts just like it: preserving string-keys etc.)

RWC’s code works very well until you get a ‘point’ value greater then ten. This is because the strcmp() function will return that 2 > 10 and 2 > 11 … 2 > 19 and so on. To compare number values over ten try a sort like this:

If your data is in an associative array that you would need to separate into columns such as those retrieved with your favorite flavor of _fetch_array() in order to be able to use multisort(), you should consider using uasort() or usort() as an alternative. Here is an example of how this could be beneficial:

(key is employee number which remains intact; rows are sorted by surname, firstname)

Note that the original ($test1) ends up being sorted even though it was never called by array_multisort(). To work around this, insert a statement to modify the copy ($test2) before calling array_multisort() on it. The following code will produce the expected "correct" results:

This seems to be a resurrection of the closed bug #8130. Also, someone reported this behavior in bug #32031, but it was incorrectly labeled "bogus" in reference to bug #25359, which is a different issue.

If you're having problems with array_multisort changing variables in global space when it is called inside a function and you're not passing in the function parameters by reference you can alleviate the problem by calling array_multisort with its parameters by reference.