Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : Array Functions : array_multisort

array_multisort

Sort multiple or multi-dimensional arrays (PHP 4, PHP 5)
bool array_multisort ( array ar1 [, mixed arg [, mixed ... [, array ...]]] )

Returns TRUE on success or FALSE on failure.

array_multisort() can be used to sort several arrays at once, or a multi-dimensional array by one or more dimensions.

Associative (string) keys will be maintained, but numeric keys will be re-indexed.

The input arrays are treated as columns of a table to be sorted by rows - this resembles the functionality of SQL ORDER BY clause. The first array is the primary one to sort by. The rows (values) in that array that compare the same are sorted by the next input array, and so on.

The argument structure of this function is a bit unusual, but flexible. The first argument has to be an array. Subsequently, each argument can be either an array or a sorting flag from the following lists.

Sorting order flags:

  • SORT_ASC - Sort in ascending order
  • SORT_DESC - Sort in descending order

Sorting type flags:

  • SORT_REGULAR - Compare items normally
  • SORT_NUMERIC - Compare items numerically
  • SORT_STRING - Compare items as strings

No two sorting flags of the same type can be specified after each array. The sorting flags specified after an array argument apply only to that array - they are reset to default SORT_ASC and SORT_REGULAR before each new array argument.

Example264.Sorting multiple arrays

<?php
$ar1
= array("10", 100, 100, "a");
$ar2 = array(1, 3, "2", 1);
array_multisort($ar1, $ar2);

var_dump($ar1);
var_dump($ar2);
?>

In this example, after sorting, the first array will contain "10", "a", 100, 100. The second array will contain 1, 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.

array(4) {
[0]=> string(2) "10"
[1]=> string(1) "a"
[2]=> int(100)
[3]=> int(100)
}
array(4) {
[0]=> int(1)
[1]=> int(1)
[2]=> string(1) "2"
[3]=> int(3)
}


Example265.Sorting multi-dimensional array

<?php
$ar
= array(
array(
"10", 11, 100, 100, "a"),
array(
1, 2, "2", 3, 1)
);
array_multisort($ar[0], SORT_ASC, SORT_STRING,
$ar[1], SORT_NUMERIC, SORT_DESC);
var_dump($ar);
?>

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

array(2) {
[0]=> array(5) {
[0]=> string(2) "10"
[1]=> int(100)
[2]=> int(100)
[3]=> int(11)
[4]=> string(1) "a"
}
[1]=> array(5) {
[0]=> int(1)
[1]=> int(3)
[2]=> string(1) "2"
[3]=> int(2)
[4]=> int(1)
}
}


Example266.Sorting database results

For this example, each element in the data array represents one row in a table. This type of dataset is typical of database records.

Example data:

volume | edition
-------+--------
67 | 2
86 | 1
85 | 6
98 | 2
86 | 6
67 | 7

The data as an array, called data. This would usually, for example, be obtained by looping with mysql_fetch_assoc().

<?php
$data
[] = array('volume' => 67, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 1);
$data[] = array('volume' => 85, 'edition' => 6);
$data[] = array('volume' => 98, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 6);
$data[] = array('volume' => 67, 'edition' => 7);
?>

In this example, we will order by volume descending, edition ascending.

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.

<?php
// Obtain a list of columns
foreach ($data as $key => $row) {
$volume[$key] = $row['volume'];
$edition[$key] = $row['edition'];
}

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

The dataset is now sorted, and will look like this:

volume | edition
-------+--------
98 | 2
86 | 1
86 | 6
85 | 6
67 | 2
67 | 7


Example267.Case insensitive sorting

Both SORT_STRING and SORT_REGULAR are case sensitive, strings starting with a capital letter will come before strings starting with a lowercase letter.

To perform a case insensitive search, force the sorting order to be determined by a lowercase copy of the original array.

<?php
$array
= array('Alpha', 'atomic', 'Beta', 'bank');
$array_lowercase = array_map('strtolower', $array);

array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $array);

print_r($array);
?>

The above example will output:

Array
(
[0] => Alpha
[1] => atomic
[2] => bank
[3] => Beta
)


Related Examples ( Source code ) » array_multisort



Code Examples / Notes » array_multisort

vermon7

When using array_multisort() on copies of arrays, it is changing all the copies, even if you modify the copy before using array_multisort().
I've avoided this bug by serializing a copy of array before calling array_multisort, and unserializg it after array_multisort() Look at the code:
<?php
$records_copy = serialize($records) ;
array_multisort ( $records[$sort_field] , $records[$sort2_field] ) ;
$records_copy = unserialize($records_copy) ;
?>


rwc

This is the simpler version of the function by AlberT.
A lot of times you have got an array like this:
$test[0]['name']='Peter';
$test[0]['points']=1;
$test[1]['name']='Mike';
$test[1]['points']=5;
$test[2]['name']='John';
$test[2]['points']=2;
You just want to sort on the index in the second dimension, ie. on points in the above example.

You can use the function below and call it like this:
$test = multi_sort($test, $key = 'points');
function multi_sort($array, $akey)
{  
 function compare($a, $b)
 {
    global $key;
    return strcmp($a[$key], $b[$key]);
 }
 usort($array, "compare");
 return $array;
}
Note: to be able to use $key in the compare function, it can not simply be passed as a parameter. It has to be declared global and set somewhere outside of compare().


jon l. -- intel352

This is my solution for a dynamic multisort, using POST values. This doesn't account for a need to sort by multiple columns at once, but could be modified for that purpose.
<?php
/**
* @desc You really should validate the posted sort direction against a list of valid possibilities.
* Options are SORT_ASC, SORT_DESC, etc, as shown in the documentation for array_multisort
*/
$sort['direction'] = $_POST['sort_direction'] ? $_POST['sort_direction'] : 'SORT_ASC';
$sort['field']   = $_POST['sort_field'] ? $_POST['sort_field'] : 'value';
$array_to_sort = array();
$array_to_sort['TestCase1'] = array('name'=>'Test1','value'=>'218');
$array_to_sort['TestCase2'] = array('name'=>'Test2','value'=>'10');
$array_to_sort['TestCase3'] = array('name'=>'Test3','value'=>'64');

/**
* @desc Build columns using the values, for sorting in php
*/
$sort_arr = array();
foreach($array_to_sort AS $uniqid => $row){
foreach($row AS $key=>$value){
$sort_arr[$key][$uniqid] = $value;
}
}

print '<b>Before sorting</b>:
<pre>';
print_r($array_to_sort);
print '</pre>';

if($sort['direction']){
array_multisort($sort_arr[$sort['field']], constant($sort['direction']), $array_to_sort);
}
print '<b>After sorting</b>:
<pre>';
print_r($array_to_sort);
print '</pre>';

?>
This example prints out:
Before sorting:
Array
(
   [TestCase1] => Array
       (
           [name] => Test1
           [value] => 218
       )
   [TestCase2] => Array
       (
           [name] => Test2
           [value] => 10
       )
   [TestCase3] => Array
       (
           [name] => Test3
           [value] => 64
       )
)
After sorting:
Array
(
   [TestCase2] => Array
       (
           [name] => Test2
           [value] => 10
       )
   [TestCase3] => Array
       (
           [name] => Test3
           [value] => 64
       )
   [TestCase1] => Array
       (
           [name] => Test1
           [value] => 218
       )
)


cesar sirvent

There is a problem with array_multisort in languages other than English.
For special chars, as A with accent (Á), the sorting does not correspond to what might expect from a MySQL SELECT with ORDER BY.
For example
<?php

      foreach ($students as $key => $row){
         $surname[$key] = $row['surname'];
      }
      array_multisort($surname, SORT_ASC, $students);
?>
will sort the array in this way: ABADIA, ALVAREZ, BUÑUEL, ZUBIETA, ÁLVARES
while a MySQL SELECT with ORDER BY nombre ASC will yield
ABADIA, ÁLVARES, ALVEREZ, BUÑUEL, ZUBIETA
as A and Á are considered two different representations of the same letter.


shmee

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:
$test = multi_sort($test, $key = 'points');
function multi_sort($array, $akey)
{
 function compare($a, $b)
 {
    global $key;
    if ($a[$key]>$b[$key]){
        $varcmp = "1";
        return $varcmp;
    }
    elseif ($a[$key]<$b[$key]){
        $varcmp = "-1";
        return $varcmp;
    }
    elseif ($a[$key]==$b[$key]){
        $varcmp = "0";
        return $varcmp;
    }
 }
 usort($array, "compare");
 return $array;
}


php a-t-the-r-a-t-e chir.ag

Re: phu at kungphu, 19-Dec-2005 11:36
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.)
<?php
 function arrayColumnSort()
 {
   $n = func_num_args();
   $ar = func_get_arg($n-1);
   if(!is_array($ar))
     return false;
   for($i = 0; $i < $n-1; $i++)
     $col[$i] = func_get_arg($i);
   foreach($ar as $key => $val)
     foreach($col as $kkey => $vval)
       if(is_string($vval))
         ${"subar$kkey"}[$key] = $val[$vval];
   $arv = array();
   foreach($col as $key => $val)
     $arv[] = (is_string($val) ? ${"subar$key"} : $val);
   $arv[] = $ar;
   call_user_func_array("array_multisort", $arv);
   return $ar;
 }
 $test["pete"]['points']=1;
 $test["pete"]['name']='Peter';
 $test["mike"]['points']=5;
 $test["mike"]['name']='Mike';
 $test["zoo"]['points']=2;
 $test["zoo"]['name']='John Zoo';
 $test["ab"]['points']=2;
 $test["ab"]['name']='John Ab';
 $test1 = $test;
 asort($test1);
 $test2 = arrayColumnSort("points", SORT_DESC, SORT_NUMERIC, "name", SORT_ASC, SORT_STRING, $test);
 print_r($test1); // asort
 print_r($test2); // arrayColumnSort
?>
Output from asort:
Array
(
   [pete] => Array
       (
           [points] => 1
           [name] => Peter
       )
   [ab] => Array
       (
           [points] => 2
           [name] => John Ab
       )
   [zoo] => Array
       (
           [points] => 2
           [name] => John Zoo
       )
   [mike] => Array
       (
           [points] => 5
           [name] => Mike
       )
)
Output from arrayColumnSort:
Array
(
   [mike] => Array
       (
           [points] => 5
           [name] => Mike
       )
   [ab] => Array
       (
           [points] => 2
           [name] => John Ab
       )
   [zoo] => Array
       (
           [points] => 2
           [name] => John Zoo
       )
   [pete] => Array
       (
           [points] => 1
           [name] => Peter
       )
)


brettz9 throu gh yah

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:
<?php
array_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);
?>
which, when $ar1 and $ar2 are dumped gives:
array(4) {
 [0]=> string(2) "10"
 [1]=> string(1) "a"
 [2]=> int(100)
 [3]=> int(100)
}
array(4) {
 [0]=>  int(1)
 [1]=>  int(1)
 [2]=>  int(3)
 [3]=>  string(1) "2"
}


phu

Notepad's example using asort/arsort will -not- work unless 'points' is defined -before- 'name'.
Running the posted code sorts by 'name', which was not the point of the previous posts.  Defining 'points' as 'apoints' also did not work; however, defining 'points' first yields correct sorting:
$test[0]['points']=1;
$test[0]['name']='Peter';
$test[1]['points']=5;
$test[1]['name']='Mike';
$test[2]['points']=2;
$test[2]['name']='John';
asort($test);
It appears asort uses the first defined element to sort a multidimensional array.


peter dot graham

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.
<?php
function array_key_multi_sort($arr, $l , $f='strnatcasecmp')
{
usort($arr, create_function('$a, $b', "return $f(\$a['$l'], \$b['$l']);"));
return($arr);
}
?>


kes

It is very handy to have function, which sort like this:
$arrayToSort[]= array(0 => ".",               "type" => "dir");
$arrayToSort[]= array(0 => "qf",              "type" => "file");
$arrayToSort[]= array(0 => "..",              "type" => "dir");
$arrayToSort[]= array(0 => "text.txt",      "type" => "file");
$arrayToSort[]= array(0 => "hello",          "type" => "dir");
//first sort by the column 'type', then sort by the column '0'
$howToSort= array('type'=> 'asc', 0=> 'desc');
multisort($arrayToSort, $howToSort);
The result:
0           |       type
----------------------------
.           | dir
..           | dir
hello       | dir
text.txt    | file
qf          | file


kencomer

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)
<?php
function namecmp( $row1,$row2 )
{
   $first = strcmp($row1['surname'], $row2['surname']) ;
   if ( $first )
       return $first ;
   else
       return strcmp($row1['name'], $row2['name']) ;
}
     $test = array( '11122202' => array('empno'=>11122202,'name'=>'geezer'
               ,'surname'=>'schmidt','age'=>96,'sex'=>'male')
           ,'11122204' => array('empno'=>11122204,'name'=>'coed'
               ,'surname'=>'beaujolais','age'=>18,'sex'=>'female')
           ,'11122206' => array('empno'=>11122206,'name'=>'immortal'
               ,'surname'=>'ramos','age'=>21,'sex'=>'male')
           ,'11122208' => array('empno'=>11122208,'name'=>'babyface'
               ,'surname'=>'brown','age'=>1,'sex'=>'male')
           ,'11122210' => array('empno'=>11122210,'name'=>'exjock'
               ,'surname'=>'gatti','age'=>48,'sex'=>'male')
           ,'11122212' => array('empno'=>11122212,'name'=>'jailbait'
               ,'surname'=>'muhammed','age'=>15,'sex'=>'female') )
           ;
echo "<pre>" ;
print_r( $test ) ;
uasort($test,'namecmp') ;
echo "----sorting----<br \>";
print_r( $test ) ;
echo "</pre>" ;
?>
Array
(
   [11122202] => Array
       (
           [empno] => 11122202
           [name] => geezer
           [surname] => schmidt
           [age] => 96
           [sex] => male
       )
   [11122204] => Array
       (
           [empno] => 11122204
           [name] => coed
           [surname] => beaujolais
           [age] => 18
           [sex] => female
       )
   [11122206] => Array
       (
           [empno] => 11122206
           [name] => immortal
           [surname] => ramos
           [age] => 21
           [sex] => male
       )
   [11122208] => Array
       (
           [empno] => 11122208
           [name] => babyface
           [surname] => brown
           [age] => 1
           [sex] => male
       )
   [11122210] => Array
       (
           [empno] => 11122210
           [name] => exjock
           [surname] => gatti
           [age] => 48
           [sex] => male
       )
   [11122212] => Array
       (
           [empno] => 11122212
           [name] => jailbait
           [surname] => muhammed
           [age] => 15
           [sex] => female
       )
)
----sorting----
Array
(
   [11122204] => Array
       (
           [empno] => 11122204
           [name] => coed
           [surname] => beaujolais
           [age] => 18
           [sex] => female
       )
   [11122208] => Array
       (
           [empno] => 11122208
           [name] => babyface
           [surname] => brown
           [age] => 1
           [sex] => male
       )
   [11122210] => Array
       (
           [empno] => 11122210
           [name] => exjock
           [surname] => gatti
           [age] => 48
           [sex] => male
       )
   [11122212] => Array
       (
           [empno] => 11122212
           [name] => jailbait
           [surname] => muhammed
           [age] => 15
           [sex] => female
       )
   [11122206] => Array
       (
           [empno] => 11122206
           [name] => immortal
           [surname] => ramos
           [age] => 21
           [sex] => male
       )
   [11122202] => Array
       (
           [empno] => 11122202
           [name] => geezer
           [surname] => schmidt
           [age] => 96
           [sex] => male
       )
)


kat dot n0spam

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.
array_multisort(&$a, SORT_DESC, &$b);
More details here in my bug report:
http://www.php.net/bugs.php?id=12936


meddle

If you want to sort a multidomensional array by key name you cannot use array_multisort. ie: for an array named $archivos that prints like this:
Array
(
   [0] => Array
       (
           [index] => 0
           [name] => test
       )
   [1] => Array
       (
           [index] => 0
           [name] => watertaxi.jpg
       )
   [2] => Array
       (
           [index] => 0
           [name] => 2_0003.JPG
       )
   [3] => Array
       (
           [index] => 0
           [name] => 24A_0025.JPG
       )
   [4] => Array
       (
           [index] => 1
           [name] => _CIMG3501.JPG
       )
)
If I wanted to order by "name" I'd use:
function comparar($a, $b) {
       return strnatcasecmp($a["name"], $b["name"]);
}
usort($archivos, "comparar");
This function performs a case insensitive string comparison using a "natural order" algorithm (strnatcasecmp), resulting in:
Array
(
   [0] => Array
       (
           [index] => 0
           [name] => 2_0003.JPG
       )
   [1] => Array
       (
           [index] => 0
           [name] => 24A_0025.JPG
       )
   [2] => Array
       (
           [index] => 0
           [name] => test
       )
   [3] => Array
       (
           [index] => 0
           [name] => watertaxi.jpg
       )
   [4] => Array
       (
           [index] => 1
           [name] => _CIMG3501.JPG
       )
)


lpchip

I was looking for a way to dynamically multisort my array.
By dynamically I mean that its not static what column will be sorted and if its ASC or DESC, and the ability to have more than one sorts.
This is the way a database would allow you to do.
The best way to dynamically do this, is by using eval.
The code below is partly what I used. (eg, I left out where the arrays were made and stuff, but the important part is here.)
<?
$orderby_arr = array("col1 ASC";"col2 DESC");
// prepare multisort using eval
$eval_sort  = "array_multisort(";
if ($orderby !="") {
$orderby_arr_c = count($orderby_arr);
for ($orderby_walk=0; $orderby_walk < $orderby_arr_c; $orderby_walk++) {
$pos = strpos($orderby_arr[$orderby_walk], " ");
$orderby_col = substr($orderby_arr[$orderby_walk], 0, $pos);
$orderby_type = substr($orderby_arr[$orderby_walk], $pos+1);
$eval_sort .= "\$this->OrderBy[$orderby_col]" . ", SORT_$orderby_type,";
}
}

$eval_sort .= " \$this->Current_Query);";
// if there's an array, sort it.
if ($this->Current_Query_m != -1) eval($eval_sort);
?>


mail

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
ex/
<?php
//Here is an array example
$test[0]['name'] = "David";
$test[0]['age'] = 28;
$test[1]['name'] = "Dennis";
$test[1]['age'] = 23;
$test[2]['name'] = "Joseph";
$test[2]['age'] = 42;
//Here is the Function
function sortmddata($array, $by, $order, $type){
//$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
foreach ($array as $key => $row) {

foreach ($vals as $names){
$keyname = "sort$names";
$test = array();
$test[$key] = $row[$names];
$$keyname = array_merge($$keyname,$test);

}
}
//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
if ($order == "DESC"){
if ($type == "num"){
array_multisort($$sortby,SORT_DESC, SORT_NUMERIC,$array);
} else {
array_multisort($$sortby,SORT_DESC, SORT_STRING,$array);
}
} else {
if ($type == "num"){
array_multisort($$sortby,SORT_ASC, SORT_NUMERIC,$array);
} else {
array_multisort($$sortby,SORT_ASC, SORT_STRING,$array);
}
}
//This just goed through and asks the additional arguments
//What they are doing and are doing variations of
//the multisort
return $array;
}
//Now to test it
$test = sortmddata($test,'age','ASC','num');
print_r ($test);
//This will return
//Array (
//[0] => Array ([name] => Dennis [age] => 23 )
//[1] => Array ( [name] => David [age] => 28 )
//[2] => Array ( [name] => Joseph [age] => 42 )
//)
?>
There you go... please let me know what you think if you like.


michael oelze

I try array_multisort at first and it seems to work well. But then I program a page with cached datas (the arrays were saved in a session). Suddenly the sort function doesn't seem to work. There was no error in my script, so I try the reference on the variables. Then he manage to sort the arrays again.
So it seems that if you save your Arrays in a session your arrays are global variables and then 'array_multisort' doesn't sort the arrays despite it gives back 'true'.
You must reference your variables and all work well:
session_start(); // restore variables (Arrays etc.)
.....
.....
array_multisort(&$Array1,&$Array2,&$Array3,...);
....
$_SESSION["Array1"]=$Array1;//
$_SESSION["Array2"]=$Array2;//Save Arrays in Session Data
$_SESSION["Array3"]=$Array3;//
......
Now you can store your Data Arrays in your Session and are able to sort them as you like...


scott

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:
$clsVar =& new abc();
$newData = $clsVar->data;
foreach ($newData as $key => $row)
{
  $position[$key]  = $key;    
}
array_multisort($position, SORT_DESC, $newData);
Now newData will contain the sorted array as expected.  
Hopefully this helps someone else!


ricardo

Hi,
Modded the function from KES,
goals:
- Object oriented
- string comparision using naturalordening
code:
<?
class HtmlTable{
var $sortorder;
var $rows;
//row adding stuf and constructor removed
function sort($sortorder){
if(is_array($sortorder)){
$this->sortorder=$sortorder;
usort($this->rows,array(&$this,'sort_compare'));
}
}
function sort_compare($a,$b){//sort function
$result=0;
foreach($this->sortorder as $key=>$value){
$result=strnatcmp($a[$key],$b[$key]);
if($result==0)continue;
if($value=='desc')$result=$result*-1;
break;
}
return $result;
}
}
?>


notepad

for you guys trying to sort scores on an associative multi-dimensional array, why are you creating your own functions?
<?php
$test[0]['name']='Peter';
$test[0]['points']=1;
$test[1]['name']='Mike';
$test[1]['points']=5;
$test[2]['name']='John';
$test[2]['points']=2;
asort($test);
// or even arsort();
?>
the above seems to work for me...


rquadling

Extending KES's example (http://www.php.net/manual/en/function.array-multisort.php#68452) to look like array_multisort().
NOTE: Fully commented code is available at http://rquadling.php1h.com (sorry for the ads).
The syntax is the same as array_multisort().
You also have 3 additional parameters you can use:
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.
<?php
define ('AMC_SORT_STRING_CASELESS', SORT_STRING + 1);
define ('AMC_LOSE_ASSOCIATION', 1001);
define ('AMC_KEEP_ASSOCIATION', 1002);
define ('AMC_SORT_ORDER', 1003);
define ('AMC_SORT_TYPE', 1004);
function array_multisort_column(array &$a_data, $m_mixed1)
{
$a_Args = func_get_args();
$i_Args = func_num_args();
$GLOBALS['a_AMC_ordering'] = array();
$a_Columns = array_keys(reset($a_data));
$b_KeepAssociation = False;
for($i_Arg = 1 ; $i_Arg < $i_Args ; )
{
if (in_array($a_Args[$i_Arg], $a_Columns))
{
$s_Column = $a_Args[$i_Arg];
$GLOBALS['a_AMC_ordering'][$a_Args[$i_Arg]] = array
(
AMC_SORT_ORDER => SORT_ASC,
AMC_SORT_TYPE => SORT_REGULAR,
);
while
(
isset($a_Args[$i_Arg + 1]) &&
in_array
(
$a_Args[$i_Arg + 1],
array
(
AMC_KEEP_ASSOCIATION,
AMC_LOSE_ASSOCIATION,
AMC_SORT_STRING_CASELESS,
SORT_ASC,
SORT_DESC
SORT_NUMERIC,
SORT_REGULAR,
SORT_STRING,
),
True
)
)
{
if (in_array($a_Args[$i_Arg + 1], array(SORT_ASC, SORT_DESC), True))
{
$GLOBALS['a_AMC_ordering'][$s_Column][AMC_SORT_ORDER] = $a_Args[$i_Arg + 1];
}
elseif (in_array($a_Args[$i_Arg + 1], array(SORT_REGULAR, SORT_NUMERIC, SORT_STRING, AMC_SORT_STRING_CASELESS), True))
{
$GLOBALS['a_AMC_ordering'][$s_Column][AMC_SORT_TYPE] = $a_Args[$i_Arg + 1];
}
elseif (AMC_KEEP_ASSOCIATION == $a_Args[$i_Arg + 1])
{
$b_KeepAssociation = True;
}
++$i_Arg;
}
}
++$i_Arg;
}
$s_Sorter = ($b_KeepAssociation ? 'uasort' : 'usort');
$b_Result = $s_Sorter($a_data, 'array_multisort_column_cmp');
unset($GLOBALS['a_AMC_ordering']);
return $b_Result;
}
function array_multisort_column_cmp(array &$a_left, array &$a_right)
{
$i_Result = 0;
foreach($GLOBALS['a_AMC_ordering'] as $s_Column => $a_ColumnData)
{
switch ($a_ColumnData[AMC_SORT_TYPE])
{
case SORT_NUMERIC :
$i_ColumnCompareResult =
((intval($a_left[$s_Column]) == intval($a_right[$s_Column]))
?
0
:
((intval($a_left[$s_Column]) < intval($a_right[$s_Column]))
?
-1
:
1
)
);
break;
case SORT_STRING :
$i_ColumnCompareResult = strcmp((string)$a_left[$s_Column], (string)$a_right[$s_Column]);
break;
case AMC_SORT_STRING_CASELESS :
$i_ColumnCompareResult = strcasecmp((string)$a_left[$s_Column], (string)$a_right[$s_Column]);
break;
case SORT_REGULAR :
default :
$i_ColumnCompareResult =
(($a_left[$s_Column] == $a_right[$s_Column])
?
0
:
(($a_left[$s_Column] < $a_right[$s_Column])
?
-1
:
1
)
);
break;
}
if (0 == $i_ColumnCompareResult)
{
continue;
}
$i_Result = $i_ColumnCompareResult * (($a_ColumnData[AMC_SORT_ORDER] == SORT_DESC) ? -1 : 1);
break;
}
return $i_Result;
}
?>


joao

Exemple of sorting multi-dimensional arrays by one of it's fields:
$result[0]['nome']='Joao';
$result[0]['order']=5;
$result[1]['nome']='Pedro';
$result[1]['order']=1;
$result[2]['nome']='Marcelo';
$result[2]['order']=3;
foreach($result as $res)
    $sortAux[] = $res['order'];
array_multisort($sortAux, SORT_ASC, $result);
print_r($result);
produces:
Array
(
   [0] => Array
       (
           [nome] => Pedro
           [order] => 1
       )
   [1] => Array
       (
           [nome] => Marcelo
           [order] => 3
       )
   [2] => Array
       (
           [nome] => Joao
           [order] => 5
       )
)


01-dec-2006 02:58

casting the parameter arrays for array_multisort seem to make the sorting ineffective?
for example:-
<?
       foreach((array)$report_files as $report_files_i)
       {
           $file_stat = stat($report_files_i);
           $report_files_x[] = array(
               'filename'      => $report_files_i
               ,'basename'     => basename($report_files_i)
               ,'ctime'        => date("D, M j, Y",$file_stat['ctime'])
               ,'size'         => $file_stat['size']
               );
           $basename_i[] = strtolower(basename($report_files_i)); // case insensitive
       }
       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 ...


stevec

Be careful when using array_multisort() on copies of arrays, as you might end up changing the original array.  Given the following code:
<?php
$test1 = array(4,3,2,1);
$test2 = $test1;
$test3 = array('a', 'b', 'c', 'd');
array_multisort($test2, SORT_ASC, $test3);
echo 'test1:';
print_r($test1);
echo 'test2:';
print_r($test2);
echo 'test3:';
print_r($test3);
?>
You would expect:
test1:Array
(
   [0] => 4
   [1] => 3
   [2] => 2
   [3] => 1
)
test2:Array
(
   [0] => 1
   [1] => 2
   [2] => 3
   [3] => 4
)
test3:Array
(
   [0] => d
   [1] => c
   [2] => b
   [3] => a
)
However, if you run the code, you actually get:
test1:Array
(
   [0] => 1
   [1] => 2
   [2] => 3
   [3] => 4
)
test2:Array
(
   [0] => 1
   [1] => 2
   [2] => 3
   [3] => 4
)
test3:Array
(
   [0] => d
   [1] => c
   [2] => b
   [3] => a
)
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:
<?php
$test1 = array(4,3,2,1);
$test2 = $test1;
$test3 = array('a', 'b', 'c', 'd');
$test2[0] = $test2[0];                // fix
array_multisort($test2, SORT_ASC, $test3);

echo 'test1:';
print_r($test1);
echo 'test2:';
print_r($test2);
echo 'test3:';
print_r($test3);
?>
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.


toni

An example to sort an array by 3 criteria:
$recordset is an array of results from a query to a database, that I sort using $matrix as auxiliary array. First numeric, Second and Third alphabetically.
<?php
for($idx=0;$idx<$toShow;$idx++){
$matrix[0][$id]=$recordset[$id][0];
$matrix[1][$id]=$recordset[$id][1];
$matrix[2][$id]=$recordset[$id][10];
}
array_multisort($matrix[0], SORT_DESC, SORT_NUMERIC,$matrix[1], SORT_STRING, SORT_ASC,$matrix[2], SORT_STRING, SORT_ASC);
?>


scott - evolove - net - work it out

A very simple way to sort an array of associative arrays by some value is to use usort.
I needed to sort an array of 20 data structures by their 'distance' value:
Array
(
   [0] => Array
       (
           [blahblah] => blahblah
           [distance] => 6
       )
   [1] => Array
       (
         you get the idea....
Here's the code:
--------------------
usort($results, "distributor_compare");
/**
* usort callback
*/
function distributor_compare($a, $b) {
$adist = intval($a['distance']);
$bdist = intval($b['distance']);

if ($adist == $bdist) {
    return 0;
}
return ($adist < $bdist) ? -1 : 1;
}
--------------------


albert

a nice piece of code to do an "array_key_multi_sort()" is the following:
<?php
/**
* orders a multidimentional array on the base of a label-key
*
* @param $arr, the array to be ordered
* @param $l the "label" identifing the field
* @param $f the ordering function to be used,
*    strnatcasecmp() by default
* @return  TRUE on success, FALSE on failure.
*/
function array_key_multi_sort(&$arr, $l , $f='strnatcasecmp') {
       return usort($arr, create_function('$a, $b', "return $f(\$a['$l'], \$b['$l']);"));
}
?>


10-apr-2007 11:01

<?php
$strDeger = 'aaaa|bbbb|cccc';
$arrBol = explode('|',$strDeger);
array_multisort($arrBol, SORT_DESC);
for($i = 0; $i <= count($arrBol); $i++) {
echo $arrBol[$i].'<br />';
}
?>


kes http://kes.net.ua

<?
//sort by second column then first one
$orderBy=array('0'=>'desc', 'first'=>'asc');
function KES_cmp($a, $b) {
 global $orderBy;
 $result= 0;
 foreach( $orderBy as $key => $value ) {
   if( $a[$key] == $b[$key] ) continue;
   $result= ($a[$key] < $b[$key])? -1 : 1;
   if( $value=='desc' ) $result= -$result;
   break;
   }
 return $result;
 }
$result= array();
$result[]= array( 'first'=>6, 2);
$result[]= array( 'first'=>3, 2);
$result[]= array( 'first'=>1, 3);
$result[]= array( 'first'=>1, 2);
$result[]= array( 'first'=>6, 1);
print "<b>Source</b>";
print_r($result);
usort($result, 'KES_cmp');
print "<b>Result</b>";
print_r($result);
?>


Change Language


Follow Navioo On Twitter
array_change_key_case
array_chunk
array_combine
array_count_values
array_diff_assoc
array_diff_key
array_diff_uassoc
array_diff_ukey
array_diff
array_fill_keys
array_fill
array_filter
array_flip
array_intersect_assoc
array_intersect_key
array_intersect_uassoc
array_intersect_ukey
array_intersect
array_key_exists
array_keys
array_map
array_merge_recursive
array_merge
array_multisort
array_pad
array_pop
array_product
array_push
array_rand
array_reduce
array_reverse
array_search
array_shift
array_slice
array_splice
array_sum
array_udiff_assoc
array_udiff_uassoc
array_udiff
array_uintersect_assoc
array_uintersect_uassoc
array_uintersect
array_unique
array_unshift
array_values
array_walk_recursive
array_walk
array
arsort
asort
compact
count
current
each
end
extract
in_array
key
krsort
ksort
list
natcasesort
natsort
next
pos
prev
range
reset
rsort
shuffle
sizeof
sort
uasort
uksort
usort
eXTReMe Tracker