array_multisort

(PHP 4, PHP 5)

array_multisort -- 对多个数组或多维数组进行排序

说明

bool array_multisort ( array ar1 [, mixed arg [, mixed ... [, array ...]]] )

如果成功则返回 TRUE,失败则返回 FALSE

array_multisort() 可以用来一次对多个数组进行排序,或者根据某一维或多维对多维数组进行排序。

关联(string)键名保持不变,但数字键名会被重新索引。

输入数组被当成一个表的列并以行来排序――这类似于 SQL 的 ORDER BY 子句的功能。第一个数组是要排序的主要数组。数组中的行(值)比较为相同的话就按照下一个输入数组中相应值的大小来排序,依此类推。

本函数的参数结构有些不同寻常,但是非常灵活。第一个参数必须是一个数组。接下来的每个参数可以是数组或者是下面列出的排序标志。

排序顺序标志:

  • SORT_ASC - 按照上升顺序排序

  • SORT_DESC - 按照下降顺序排序

排序类型标志:

  • SORT_REGULAR - 将项目按照通常方法比较

  • SORT_NUMERIC - 将项目按照数值比较

  • SORT_STRING - 将项目按照字符串比较

每个数组之后不能指定两个同类的排序标志。每个数组后指定的排序标志仅对该数组有效 - 在此之前为默认值 SORT_ASCSORT_REGULAR

例子 1. 对多个数组排序

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

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

本例中经过排序后,第一个数组将包含 "10","a",100,100。第二个数组将包含 1,1,"2",3。第二个数组中的项目顺序完全和第一个数组中相应的项目(100 和 100)顺序一致。

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

例子 2. 对多维数组排序

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

本例中经过排序后,第一个数组将包含 10,100,100,"a"(作为字符串上升排序),第二个数组将包含 1,3,"2",1(作为数值下降排序)。

例子 3. 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);
?>

本例中在排序后,第一个数组将变成 "10",100,100,11,"a"(被当作字符串以升序排列)。第二个数组将包含 1, 3, "2", 2, 1(被当作数字以降序排列)。

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

例子 4. 对数据库结果进行排序

本例中 data 数组中的每个单元表示一个表中的一行。这是典型的数据库记录的数据集合。

例子中的数据如下:

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

数据全都存放在名为 data 的数组中。这通常是通过循环从数据库取得的结果,例如 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);
?>

本例中将把 volume 降序排列,把 edition 升序排列。

现在有了包含有行的数组,但是 array_multisort() 需要一个包含列的数组,因此用以下代码来取得列,然后排序。

<?php
// 取得列的列表
foreach ($data as $key => $row) {
    
$volume[$key]  = $row['volume'];
    
$edition[$key] = $row['edition'];
}

// 将数据根据 volume 降序排列,根据 edition 升序排列
// 把 $data 作为最后一个参数,以通用键排序
array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);
?>

数据集合现在排好序了,结果如下:

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

例子 5. 不区分大小写字母排序

SORT_STRINGSORT_REGULAR 都是区分大小写字母的,大写字母会排在小写字母之前。

要进行不区分大小写的排序,就要按照原数组的小写字母拷贝来排序。

<?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);
?>

上例将输出:

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

【译者注】本函数相当有用,为有助于理解,请再看下面这个例子:

例子 6. 名次排列

<?php
$grade
= array("score" => array(70, 95, 70.0, 60, "70"),
               
"name" => array("Zhang San", "Li Si", "Wang Wu",
                               
"Zhao Liu", "Liu Qi"));
array_multisort($grade["score"], SORT_NUMERIC, SORT_DESC,
                
// 将分数作为数值,由高到低排序
                
$grade["name"], SORT_STRING, SORT_ASC);
                
// 将名字作为字符串,由小到大排序
var_dump($grade);
?>

上例将输出:

array(2) {
  ["score"]=>
  array(5) {
    [0]=>
    int(95)
    [1]=>
    string(2) "70"
    [2]=>
    float(70)
    [3]=>
    int(70)
    [4]=>
    int(60)
  }
  ["name"]=>
  array(5) {
    [0]=>
    string(5) "Li Si"
    [1]=>
    string(6) "Liu Qi"
    [2]=>
    string(7) "Wang Wu"
    [3]=>
    string(9) "Zhang San"
    [4]=>
    string(8) "Zhao Liu"
  }
}

本例中对包含成绩的数组 $grade 按照分数(score)由高到低进行排序,分数相同的人则按照名字(name)由小到大排序。排序后李四 95 分为第一名,赵六 60 分为第五名没有异议。张三、王五和刘七都是 70 分,他们的名次则由其姓名的字母顺序排列,Liu 在前,Wang 在后而 Zhang 在最后。为了区别,三个 70 分分别用了整数,浮点数和字符串来表示,可以在程序输出中清楚地看到它们排序的结果。


add a note add a note User Contributed Notes
brettz9 throu gh yah
14-Sep-2006 03:04
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"
}
ricardo
04-Sep-2006 08:47
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;
   }
}
?>
LPChip
28-Aug-2006 09:04
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);
?>
RQuadling at GMail dot com
07-Aug-2006 08:53
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;
   }
?>
KES http://kes.net.ua
27-Jul-2006 08:30
<?
//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);
?>
KES
27-Jul-2006 07:35
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
Cesar Sirvent
18-May-2006 12:43
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, BUUEL, ZUBIETA, LVARES

while a MySQL SELECT with ORDER BY nombre ASC will yield

ABADIA, LVARES, ALVEREZ, BUUEL, ZUBIETA

as A and  are considered two different representations of the same letter.
scott - evolove - net - work it out
23-Mar-2006 11:51
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;   
}
--------------------
peter dot graham at tcat dot ac dot uk
16-Feb-2006 11:16
Many thanks to AlberT at SuperAlberT dot it for his useful and elegant function. I have made some small alterations so it doesnt 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);
}

?>
mail at theopensource dot com
01-Feb-2006 03:34
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.
php a-t-the-r-a-t-e chir.ag
06-Jan-2006 06:10
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
       )

)
phu at kungphu
20-Dec-2005 03:36
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.
notepad at codewalkers dot com
10-Dec-2005 08:33
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...
Shmee
30-Sep-2005 09:46
RWCs 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;
}
RWC
26-Sep-2005 04:45
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().
AlberT at SuperAlberT dot it
18-Jul-2005 09:59
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']);"));
}
?>
kencomer at kencomer dot com
13-Jun-2005 02:48
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
       )

)
Michael Oelze at M (myname) T GMXdotDE
26-Apr-2005 12:15
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...
stevec at NO-/ dot /-SPAM dot qiguang dot net
13-Apr-2005 11:19
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.
joao at intrasystems dot com dot br
08-Apr-2005 03:27
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
       )

)
Toni
10-Nov-2004 07:30
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);
?>
meddle at dzygn.com
05-Oct-2004 10:40
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
       )

)
kat dot n0spam at audiogalaxy dot com
24-Aug-2001 01:25
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