array_multisort

(PHP 4, PHP 5, PHP 7, PHP 8)

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

说明

array_multisort ( array &$array1 , mixed $array1_sort_order = SORT_ASC , mixed $array1_sort_flags = SORT_REGULAR , mixed $... = ? ) : bool

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

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

Note:

如果两个成员完全相同,那么它们在排序数组中的相对顺序是未定义的。

参数

array1

要排序的 array

array1_sort_order

之前 array 参数要排列的顺序。 SORT_ASC 按照上升顺序排序, SORT_DESC 按照下降顺序排序。

此参数可以和 array1_sort_flags 互换,也可以完全删除,默认是 SORT_ASC

array1_sort_flags

array 参数设定选项:

排序类型标志:

  • SORT_REGULAR - 将项目按照通常方法比较(不修改类型)
  • SORT_NUMERIC - 按照数字大小比较
  • SORT_STRING - 按照字符串比较
  • SORT_LOCALE_STRING - 根据当前的本地化设置,按照字符串比较。 它会使用 locale 信息,可以通过 setlocale() 修改此信息。
  • SORT_NATURAL - 以字符串的"自然排序",类似 natsort()
  • SORT_FLAG_CASE - 可以组合 (按位或 OR) SORT_STRING 或者 SORT_NATURAL 大小写不敏感的方式排序字符串。

参数可以和 array1_sort_order 交换或者省略,默认情况下是 SORT_REGULAR

...

可选的选项,可提供更多数组,跟随在 sort order 和 sort flag 之后。 提供的数组和之前的数组要有相同数量的元素。 换言之,排序是按字典顺序排列的。

返回值

成功时返回 true, 或者在失败时返回 false

更新日志

版本 说明
5.4.0 array1_sort_flags 增加 SORT_NATURALSORT_FLAG_CASE 选项。
5.3.0 array1_sort_flags 增加选项 SORT_LOCALE_STRING

范例

Example #1 多个数组排序

<?php
$ar1 
= array(101001000);
$ar2 = array(1324);
array_multisort($ar1$ar2);

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

这个例子里,排序后,第一个数组会包含 0、 10、 100、 100。 第二个数组会包含 4、1、 2、 3。 第二个数组里的项目对应第一个数组后也进行了排序(100 和 100)。

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

Example #2 排序多维数组

<?php
$ar 
= array(
       array(
"10"11100100"a"),
       array(   
1,  2"2",   3,   1)
      );
array_multisort($ar[0], SORT_ASCSORT_STRING,
                
$ar[1], SORT_NUMERICSORT_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)
  }
}

Example #3 对数据库结果进行排序

本例中 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($volumeSORT_DESC$editionSORT_ASC$data);
?>

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

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

Example #4 不区分大小写字母排序

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

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

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

array_multisort($array_lowercaseSORT_ASCSORT_STRING$array);

print_r($array);
?>

以上例程会输出:

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

参见

User Contributed Notes

498936940 at qq dot com 09-Oct-2021 03:00
Arbitrarily sort the two-dimensional array according to multiple keys:

```
array_multisort (
    array_column($array, 'key1'), SORT_ASC,
    array_column($array, 'key2'), SORT_DESC,
    array_column($array, 'key3'), SORT_ASC,
    array_column($array, 'key4'), SORT_DESC,
    $array
);
```
lingtalfi 25-Mar-2021 02:44
For database like sorting, here is my 2 cents:

<?php
/**
 * The RowsSortHelperTool class.
 */
class RowsSortHelperTool
{

   
/**
     * Sorts the given array, based on the given sorts.
     *
     * The sorts argument is an array of field => direction,
     *
     * with:
     *
     * - field: string, the name of the property to sort the rows with
     * - direction: string (asc|desc), the direction of the sort
     *
     *
     * @param array $rows
     * @param array $sorts
     * @return array
     */
   
public static function sort(array &$rows, array $sorts)
    {

       
$args = [];

        foreach (
$sorts as $field => $direction) {
           
$col = array_column($rows, $field);
           
$args[] = $col;

            if (
'asc' === $direction) {
               
$args[] = SORT_ASC;
            } else {
               
$args[] = SORT_DESC;
            }
        }
       
$args[] = &$rows;
       
call_user_func_array("array_multisort", $args);
    }
}

?>

Use it like this:

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

RowsSortHelperTool::sort($data, [
   
'volume' => 'desc',
   
'edition' => 'asc',
   
'mine' => 'desc',
]);

az($data);

?>

Will display something like this:

array(7) {
  [0] => array(3) {
    ["volume"] => int(98)
    ["edition"] => int(2)
    ["mine"] => int(5)
  }
  [1] => array(3) {
    ["volume"] => int(86)
    ["edition"] => int(1)
    ["mine"] => int(5)
  }
  [2] => array(3) {
    ["volume"] => int(86)
    ["edition"] => int(6)
    ["mine"] => int(5)
  }
  [3] => array(3) {
    ["volume"] => int(86)
    ["edition"] => int(6)
    ["mine"] => int(4)
  }
  [4] => array(3) {
    ["volume"] => int(85)
    ["edition"] => int(6)
    ["mine"] => int(5)
  }
  [5] => array(3) {
    ["volume"] => int(67)
    ["edition"] => int(2)
    ["mine"] => int(5)
  }
  [6] => array(3) {
    ["volume"] => int(67)
    ["edition"] => int(7)
    ["mine"] => int(5)
  }
}
dwalter at seznam dot cz 31-Oct-2019 08:45
My solution for multidimensional asociative array in my language, which respect all characters of alphabet
<?php
  setlocale
(LC_COLLATE, 'cs_CZ.utf-8');
 
$prijmeni_zamestnancu = array_column($DBzamestnanci, 'prijmeni');
 
array_multisort($prijmeni_zamestnancu, SORT_ASC, SORT_LOCALE_STRING, $DBzamestnanci);
?>
qasastechnology at gmail dot com 13-Feb-2019 09:48
Case insensitive sorting
To perform a case insensitive sort

$array = [
     [
       'name' => 'b',
       'label' => 'ball'
    ],
     [
       'name' => 'a',
       'label' => 'apple'
    ],
     [
       'name' => 'l',
       'label' => 'Lighting'
    ],
     [
       'name' => 'w',
       'label' => 'With'
    ]

];
 
public function sortArray($array) {
       
        if (count($array)) {
            array_multisort(array_map(function($element) {
                return strtolower($element['label']);
            }, $array), SORT_ASC, $array);
        }
       
        return $array;
    }
Hayley Watson 09-Jul-2018 01:12
Thin wrapper around array_multisort() so that, when sorting an array of associative arrays, you can specify the columns to sort on by their name, instead of having to pull them out as explicit arrays. Note that you can sort on numerically-indexed columns too, provided you cast the index to a string first (otherwise they'll get confused with the SORT_* constants).

<?php
function array_multisort_by_column(&$array, ...$spec)
{
    return
array_multisort($array, ...array_map(function($s)use($array)
    {
        return
is_string($s) ? array_column($array, $s) : $s;
    },
$spec));
}
?>
ArkieGuy 10-Jan-2018 04:02
<?php 

/**
 *  array_multisort wrapper function -- Sorts Data array on array of Keys
 * 
 *  $data : This is the multidiminsional array to sort
 *  $keys : An array of arrays holding "Key" field names and optional Order / flags
 * 
 *  Example:  $keys[2] = [ 'Animal', SORT_DESC, SORT_REGULAR | SORT_FLAG_CASE ];
 *            $keys[1] = [ 'Name' ];
 *
 *  Syntax:   if( multiSort( $data, $keys ) ) print_r( $data );
 *
 *  Returns TRUE on success or FALSE on failure.
 */
function multiSort( &$data, $keys ) {

 
// Sort the Keys - this allows for passing in the key array out of order
 
ksort( $keys );
 
 
//  Walk Keys array building arguments to pass to call_user_function
  //  (must be indexed 0-n with n being the data to sort)
 
foreach( $keys as $key ) {
   
//  Walk through the list of key parameters
   
foreach( $key as $element => $value )
        if(
$element == 0 )
           
//  Add an array containing the column values for the named $data column
           
$args[] = array_column( $data, $value );
        else
           
//  Add the inetger value passed in for the order / flags
            //  NOTE: if you try to send a string value (like from an INI) to
            //        array_multisort for sort_order or sort_flags, you get
            //        "Argument #x is expected to be an array or a sort flag".
            //        Casting to int solves this issue
           
$args[] = (int)$value;
  }
 
 
//  Add the array to be sorted to the arg list 
 
$args[] = &$data;
 
 
//  Call array_multisort to sort the array in keys order
 
return( call_user_func_array( 'array_multisort', $args ) );
}

/* Example */

echo "<PRE>";

//  Data array (can be associative array or you can use column number)
$data = [
  [
'Name' => 'Brown', 'Animal' => 'Dog'],
  [
'Name' => 'Smith', 'Animal' => 'Cat'],
  [
'Name' => 'Jones', 'Animal' => 'Dog'],
  [
'Name' => 'Jones', 'Animal' => 'Pig'],
  [
'Name' => 'Bennett', 'Animal' => 'Cat'],
  [
'Name' => 'Astor', 'Animal' => 'Cat'],
  [
'Name' => 'Jones', 'Animal' => 'Cat'],
];

//  Array containing "keys" - each key is the name of the column and
//    optionally a sort order and / or  sort flags
//  Will sort by Name and then Animal because the keys array is key sorted
//    before it's used.
$keys[2] = [ 'Animal', SORT_DESC, SORT_REGULAR | SORT_FLAG_CASE ];
$keys[1] = [ 'Name' ]; 

//call the wrapper function
if( ! multiSort( $data, $keys ) )
    die(
'Sort Failed' );
   
print_r( $data );
?>
walterquez at gmail dot com 03-Jan-2018 06:11
To sort a simple multi dimensional array, use the array itself as the modifier. This will sort based on the first column. No need to write a custom function.

$data = array(
    array('volume' => 67, 'edition' => 2),
    array('volume' => 86, 'edition' => 1),
    array('volume' => 85, 'edition' => 6),
    array('volume' => 98, 'edition' => 2),
    array('volume' => 86, 'edition' => 6),
    array('volume' => 67, 'edition' => 7)
)

array_multisort($data, $data);
faugeron dot loic at gmail dot com 17-May-2016 07:14
Improving Example #3 (Sorting database results): using <?php array_column ?> (PHP >= 5.5) and <?php call_user_func_array ?> it becomes possible to build your sortings (sorting by one or many fields):

<?php

$data
= [
    [
       
'id' => '168ac7f8-c918-4e99-90ee-5d7590fe61ce',
       
'name' => 'Arthur Dent',
    ],
    [
       
'id' => 'e3ad45ee-7cae-4cca-bd7b-2eb6b57b6457',
       
'name' => 'Ford Prefect',
    ],
    [
       
'id' => 'a426aef2-19e2-412a-8339-5458cf6ae416',
       
'name' => 'Trillian Astra',
    ],
];
$sortings = [
    [
       
'field' => 'id',
       
'direction' => SORT_DESC,
    ],
];

$args = [];
$key = 0;
foreach (
$sortings as $sorting) {
   
$args[$key] = array_column($data, $sorting['field']);
   
$args[$key + 1] = $sorting['direction'];
   
$key += 2;
}
$args[] = $data;
call_user_func_array('array_multisort', $args);

// $data is now sorted by ID in descending order.
?>
matt at bosc dot io 05-May-2016 09:02
One-liner function to sort multidimensionnal array by key, thank's to array_column

<?php

array_multisort
(array_column($array, 'key'), SORT_DESC, $array);

?>
nospam at nospam dot com 23-Oct-2015 10:30
Super easy and simple way to sort a keyed multiarray while maintaining all associative keys, including numeric!

Preserves the original multiarray order if the sorting values are equal.

<?php
// sorts multiarray by a subarray value while preserving all keys, also preserves original order when the sorting values match
function maSort($ma = '', $sortkey = '', $sortorder = 1) { // sortorder: 1=asc, 2=desc
 
if ($ma && is_array($ma) && $sortkey) { // confirm inputs
   
foreach ($ma as $k=>$a) $temp["$a[$sortkey]"][$k] = $a; // temp ma with sort value, quotes convert key to string in case numeric float
   
if ($sortorder == 2) { // descending
     
krsort($temp);
    } else {
// ascending
     
ksort($temp);
    }
   
$newma = array(); // blank output multiarray to add to
   
foreach ($temp as $sma) $newma += $sma; // add sorted arrays to output array
   
unset($ma, $sma, $temp); // release memory
   
return $newma;
  }
}
?>
matt at wennersten dot org 29-Jul-2015 09:09
Many users have contributed nifty wrapper functions for generalizing array_multisort. However, some of us may just want a simple example that illustrates how to sort an arbitrary multi-dimensional array, such as a database result set, on a named field.

Consider an array of voice recordings (Clip objects) that are stored on a file system, and referenced via a database table:

    $fetchClipQuery = "SELECT * from voiceclips";
    if ( !$result = $this->db->query($fetchClipQuery) ) {
            $errormessage = $this->db->errno;
            $errormessage .= $this->db->error;
        } else {
            while($row = $result->fetch_assoc()){
                $clip = new Clip();
                $clip->populate($row['clipURL']);
                $clips[] = array("speaker"=>$row['speaker'],"duration"=>$row['duration'],"clip"=>$clip);
            }

//we now have an array called clips[] that looks like this:

array("speaker"=>"Obama","duration"=>"22:00","clip"=>...<some arbitrary object>...);

        //suppose we want to sort the array by speaker
        $sortkeyname = "speaker";
        //do the sort
        $sortkeyarray = array();
        foreach ($clips as $key => $row){
            $sortkeyarray[$key] = $row[$sortkeyname];
        }
        array_multisort($sortkeyarray, SORT_DESC, $clips);

           //suppose we want to sort the array by duration
        $sortkeyname = "duration";
        //do the sort
        $sortkeyarray = array();
        foreach ($clips as $key => $row){
            $sortkeyarray[$key] = $row[$sortkeyname];
        }
        array_multisort($sortkeyarray, SORT_DESC, $clips);

...etc.
jcharpentier at darkmira dot fr 23-Feb-2014 05:11
There is a lack of precision for the second example :

Example #2 Sorting multi-dimensional array

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."
Robert C 09-Jan-2014 12:11
Hi,

I would like to see the next code snippet to be added to http://nl3.php.net/array_multisort

Purpose: Sort a 2-dimensional array on some key(s)

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

function MultiSort($data, $sortCriteria, $caseInSensitive = true)
{
  if( !is_array($data) || !is_array($sortCriteria))
    return false;      
  $args = array();
  $i = 0;
  foreach($sortCriteria as $sortColumn => $sortAttributes) 
  {
    $colList = array();
    foreach ($data as $key => $row)
    {
      $convertToLower = $caseInSensitive && (in_array(SORT_STRING, $sortAttributes) || in_array(SORT_REGULAR, $sortAttributes));
      $rowData = $convertToLower ? strtolower($row[$sortColumn]) : $row[$sortColumn];
      $colLists[$sortColumn][$key] = $rowData;
    }
    $args[] = &$colLists[$sortColumn];
     
    foreach($sortAttributes as $sortAttribute)
    {     
      $tmp[$i] = $sortAttribute;
      $args[] = &$tmp[$i];
      $i++;     
     }
  }
  $args[] = &$data;
  call_user_func_array('array_multisort', $args);
  return end($args);
}

Usage:

//Fill an array with random test data
define('MAX_ITEMS', 15);
define('MAX_VAL', 20);
for($i=0; $i < MAX_ITEMS; $i++)
  $data[] = array('field1' => rand(1, MAX_VAL), 'field2' => rand(1, MAX_VAL), 'field3' => rand(1, MAX_VAL) );
 
//Set the sort criteria (add as many fields as you want)
$sortCriteria =
  array('field1' => array(SORT_DESC, SORT_NUMERIC),
       'field3' => array(SORT_DESC, SORT_NUMERIC)
  );

//Call it like this: 
$sortedData = MultiSort($data, $sortCriteria, true);
Patrick Adrichem 17-Oct-2013 08:08
If you do not have PHP 5.4 installed yet and you cannot use SORT_NATURAL. This function sorts arrays natural multi-dimensional based on key value

this function can be used for arrays as

array ( name => array( key => value ) )
and

array( name => value ).

arrays as array( name => array( key => value), name => value) are not supported.

<?php
       
static function natcasesortRecursive(&$aArray)
        {
           
$bHasArrays = false;
            foreach (
$aArray as $sKey => &$mValue)
            {
                if (
true === is_array($mValue))
                {
                   
self::natcasesortRecursive($mValue);
                   
$bHasArrays = true;
                }
            }
            if (
true === $bHasArrays)
            {
               
uksort($aArray, 'strnatcasecmp');
            }
            else
            {
               
natcasesort($aArray);
            }
        }
?>
Magento-User 11-Oct-2013 03:25
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.

If this 'trick' gives a wrong order,  you need a better key.
plugboard at web dot de 04-Sep-2012 02:56
multisort an Array of Objects:

example object [$object with array of objects]: (class: test)
----------------------------------

test Object (
  [Artikel] => Array (
      [0] => test Object (
            [id] => 1
            [title] => CCCC
         )
      [1] => test Object (
            [id] => 2
            [title] => AAAA
         )
      [2] => test Object (
            [id] => 3
            [title] => DDDD
         )
      [3] => test Object (
            [id] => 4
            [title] => BBBB
         )
   )
)

----------------------------------

Simple PHP function: sort_arr_of_obj()

<?php
// --------------------------------------

/*
* -------- function arguments --------
*   $array ........ array of objects
*   $sortby ....... the object-key to sort by
*   $direction ... 'asc' = ascending
* --------
*/

function sort_arr_of_obj($array, $sortby, $direction='asc') {
    
   
$sortedArr = array();
   
$tmp_Array = array();
    
    foreach(
$array as $k => $v) {
       
$tmp_Array[] = strtolower($v->$sortby);
    }
    
    if(
$direction=='asc'){
       
asort($tmp_Array);
    }else{
       
arsort($tmp_Array);
    }
    
    foreach(
$tmp_Array as $k=>$tmp){
       
$sortedArr[] = $array[$k];
    }
    
    return
$sortedArr;
 
}
 
 
// --------------------------------------
?>

example call:
----------------------------------

<?php

$sorted
->Artikel = sort_arr_of_obj($object->Artikel,'title','asc');

?>

example result: $sorted (class: test)
----------------------------------

test Object (
  [Artikel] => Array (
      [0] => test Object (
            [id] => 2
            [title] => AAAA
         )
      [1] => test Object (
            [id] => 4
            [title] => BBBB
         )
      [2] => test Object (
            [id] => 1
            [title] => CCCC
         )
      [3] => test Object (
            [id] => 3
            [title] => DDDD
         )

   )
)

-------------------------

:)
rnacken at gmail dot com 11-Feb-2012 11:59
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 array
   
array_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
?>
nick ([AT]) nickyost ([DOT]) com 15-Sep-2011 03:36
USort function can be used to sort multidimensional arrays with almost no work whatsoever by using the individual values within the custom sort function.

This function passes the entire child element even if it is not a string. If it is an array, as would be the case in multidimensional arrays, it will pass the whole child array as one parameter.

Therefore, do something elegant like this:

<?php
    
// Sort the multidimensional array
    
usort($results, "custom_sort");
    
// Define the custom sort function
    
function custom_sort($a,$b) {
          return
$a['some_sub_var']>$b['some_sub_var'];
     }
?>

This does in 4 lines what other functions took 40 to 50 lines to do. This does not require you to create temporary arrays or anything. This is, for me, a highly preferred solution over this function.

Hope it helps!
info at ichier dot de 28-Jul-2011 08:59
if you want to sort an array by columns, this is the function to do it.

<?php
function array_csort() {        //coded by Ichier2003
   
$args = func_get_args();
   
$marray = array_shift($args);
   
$msortline = 'return(array_multisort(';
    foreach (
$args as $arg) {
       
$i++;
        if (
is_string($arg)) {
            foreach (
$marray as $row) {
               
$sortarr[$i][] = $row[$arg];
            }
        } else {
           
$sortarr[$i] = $arg;
        }
       
$msortline .= '$sortarr['.$i.'],';
    }
   
$msortline .= '$marray));';
    eval(
$msortline);
    return
$marray;
}
?>
thierryzo at hotmail dot fr 29-Jun-2011 02:27
//A very simple way to sort arrays with this kind of structure.

<?php
    $myArray
=array(
        array(
"NUMCIE" => "001","REF" => "RXL","COLOR" => "RED","L1" => 4),
        array(
"NUMCIE" => "001","REF" => "RXL","COLOR" => "BLUE","L1" => 6),
        array(
"NUMCIE" => "001","REF" => "RHQ","COLOR" => "RED","L1" => 4),
        array(
"NUMCIE" => "002","REF" => "RXL","COLOR" => "YELLOW","L1" => 8));
       
       
    foreach(
$myArray as $c=>$key) {
       
$sort_numcie[] = $key['NUMCIE'];
       
$sort_ref[] = $key['REF'];
       
$sort_color[] = $key['COLOR'];
    }

   
array_multisort($sort_numcie, SORT_ASC, $sort_ref, SORT_STRING, $myArray);
   
print_r($myArray);
   
?>    

//Result array
   
Array
(
    [0] => Array
        (
            [NUMCIE] => 001
            [REF] => RHQ
            [COLOR] => RED
            [L1] => 4
        )

    [1] => Array
        (
            [NUMCIE] => 001
            [REF] => RXL
            [COLOR] => BLUE
            [L1] => 6
        )

    [2] => Array
        (
            [NUMCIE] => 001
            [REF] => RXL
            [COLOR] => RED
            [L1] => 4
        )

    [3] => Array
        (
            [NUMCIE] => 002
            [REF] => RXL
            [COLOR] => YELLOW
            [L1] => 8
        )

)
Jaak Tamre 22-Mar-2011 06:42
I had a problem with sorting SimpleXMLElement list. I found a nice short solution.

I have an array of ticket objects: $ticketList = $xml->Tickets;

<?php
// Sort by ValidOnDate
$tickets = array();
$valid = array();
foreach (
$ticketList as $row) {
   
$tickets[] = $row;
   
$valid[] = DateHandler::parseDate($row->ValidOnDate);
}
array_multisort($valid, SORT_DESC, $tickets);
?>

Just make an array of object items you want to sort by and a new array for the same objects which will be reordered like the first array.

Ps: my own parseDate(date) returns unix timestamp for different date formats.
jimpoz at jimpoz dot com 21-Oct-2010 02:26
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().

<?php
function array_orderby()
{
   
$args = func_get_args();
   
$data = array_shift($args);
    foreach (
$args as $n => $field) {
        if (
is_string($field)) {
           
$tmp = array();
            foreach (
$data as $key => $row)
               
$tmp[$key] = $row[$field];
           
$args[$n] = $tmp;
            }
    }
   
$args[] = &$data;
   
call_user_func_array('array_multisort', $args);
    return
array_pop($args);
}
?>

The sorted array is now in the return value of the function instead of being passed by reference.

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

// Pass the array, followed by the column names and sort flags
$sorted = array_orderby($data, 'volume', SORT_DESC, 'edition', SORT_ASC);
?>
zequez at gmail dot com 06-May-2010 03:19
Easiest way I find out to sort an entire multidimensional array by one element of it:

<?php
$multiArray
= Array(
    Array(
"id" => 1, "name" => "Defg"),
    Array(
"id" => 2, "name" => "Abcd"),
    Array(
"id" => 3, "name" => "Bcde"),
    Array(
"id" => 4, "name" => "Cdef"));
$tmp = Array();
foreach(
$multiArray as &$ma)
   
$tmp[] = &$ma["name"];
array_multisort($tmp, $multiArray);
foreach(
$multiArray as &$ma)
    echo
$ma["name"]."<br/>";
               
/* Outputs
    Abcd
    Bcde
    Cdef
    Defg
*/
?>

^-^
alexander dot v at zend dot com 20-Jan-2010 03:42
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:

<?php
for (...) {
    ...
   
$sortArgs[] = &$valuesArray;
    unset(
$valuesArray);
    ...
}
?>

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.

Final code should look like this:

<?php
$sortArgs
= array();
$sortFieldValues = array();

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

call_user_func_array('array_multisort', $sortArgs);
?>
cagret at gmail dot com 20-Jun-2009 12:16
A more inuitive way of sorting multidimensional arrays using array_msort() in just one line, you don't have to divide the original array into per-column-arrays:

<?php

$arr1
= array(
    array(
'id'=>1,'name'=>'aA','cat'=>'cc'),
    array(
'id'=>2,'name'=>'aa','cat'=>'dd'),
    array(
'id'=>3,'name'=>'bb','cat'=>'cc'),
    array(
'id'=>4,'name'=>'bb','cat'=>'dd')
);

$arr2 = array_msort($arr1, array('name'=>SORT_DESC, 'cat'=>SORT_ASC));

debug($arr1, $arr2);

arr1:
   
0:
       
id: 1 (int)
       
name: aA (string:2)
       
cat: cc (string:2)
   
1:
       
id: 2 (int)
       
name: aa (string:2)
       
cat: dd (string:2)
   
2:
       
id: 3 (int)
       
name: bb (string:2)
       
cat: cc (string:2)
   
3:
       
id: 4 (int)
       
name: bb (string:2)
       
cat: dd (string:2)
arr2:
   
2:
       
id: 3 (int)
       
name: bb (string:2)
       
cat: cc (string:2)
   
3:
       
id: 4 (int)
       
name: bb (string:2)
       
cat: dd (string:2)
   
0:
       
id: 1 (int)
       
name: aA (string:2)
       
cat: cc (string:2)
   
1:
       
id: 2 (int)
       
name: aa (string:2)
       
cat: dd (string:2)

function
array_msort($array, $cols)
{
   
$colarr = array();
    foreach (
$cols as $col => $order) {
       
$colarr[$col] = array();
        foreach (
$array as $k => $row) { $colarr[$col]['_'.$k] = strtolower($row[$col]); }
    }
   
$eval = 'array_multisort(';
    foreach (
$cols as $col => $order) {
       
$eval .= '$colarr[\''.$col.'\'],'.$order.',';
    }
   
$eval = substr($eval,0,-1).');';
    eval(
$eval);
   
$ret = array();
    foreach (
$colarr as $col => $arr) {
        foreach (
$arr as $k => $v) {
           
$k = substr($k,1);
            if (!isset(
$ret[$k])) $ret[$k] = $array[$k];
           
$ret[$k][$col] = $array[$k][$col];
        }
    }
    return
$ret;

}

?>
m dot michalczyk at gmail dot com 16-May-2009 03:45
Here is useful example based on za at byza dot it solution to sort multidimensional objects by any dimension.
za at byza dot it
<?php
/* Example structure */
class person{
    function
__construct($firstName, $lastName, $title, $position){
       
$this->firstName = $firstName;
       
$this->lastName = $lastName;
       
$this->title = new title($title);
       
$this->position = new position($position);
    }
}
class
title{
    function
__construct($name){
       
$this->name = $name;
    }
   
}
class
position{
    function
__construct($name){
       
$this->name = $name;
    }

}

$array[] = new person('Piotr', 'Sobiepanek', 'b', 'b');
$array[] = new person('Piotr', 'Kowalski', 'b', 'a');
$array[] = new person('Piotr', 'Michalski', 'a', 'a');
$array[] = new person('Jozef', 'Smietana', 'a', 'b');
$array[] = new person('Jozef', 'Cmietana', 'a', 'b');
$array[] = new person('Marcin', 'Kondraciuk', 'c', 'b');
$array[] = new person('Maksym', 'Kondraciuk', 'c', 'd');
$array[] = new person('Ambrozy', 'Kondraciuk', 'c', 'd');
$array[] = new person('Alojzy', 'Kondraciuk', 'c', 'd');

array_sort($array, 'title->name', 'position->name', 'lastName');
print_r($array);

/* Source */

function hod(&$base, $path){
   
$keys = explode("->", $path);
   
$keys[0] = str_replace('$', '', $keys[0]);
   
$expression = '$ret = ';
   
$expression.= '$';
    foreach (
$keys as $key){
        if (++
$licz == 1){
           
$expression.= 'base->';           
        } else {
           
$expression.= $key.'->';
        }
    }
   
$expression = substr($expression, 0, -2);
   
$expression.= ';';
    eval(
$expression);
    return
$ret;
}

function
array_sort_func($a,$b=NULL) {
   static
$keys;
   if(
$b===NULL) return $keys=$a;
   foreach(
$keys as $k) {
      if(
$k[0]=='!') {
        
$k=substr($k,1);
         if(
hod($a, '$a->'.$k)!==hod($b, '$b->'.$k)) {
            return
strcmp(hod($b, '$b->'.$k),hod($a, '$a->'.$k));
         }
      }
      else if(
hod($a, '$a->'.$k)!==hod($b, '$b->'.$k)) {
         return
strcmp(hod($a, '$a->'.$k),hod($b, '$b->'.$k));
      }
   }
   return
0;
}

function
array_sort(&$array) {
   if(!
$array) return $keys;
  
$keys=func_get_args();
  
array_shift($keys);
  
array_sort_func($keys);
  
usort($array,"array_sort_func");      
}
?>
mech.cx 28-Mar-2009 12:04
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.

<?php

$points
= array(1, 5, 2, 2);
$names  = array('peter', 'mike', 'john Zoo', 'john Ab');

$source = array (
  array (
'points' => 1, 'name' => 'Peter'),
  array (
'points' => 5, 'name' => 'Mike'),
  array (
'points' => 2, 'name' => 'John Zoo'),
  array (
'points' => 2, 'name' => 'John Ab')
);

call_user_func_array('array_multisort', array($points, SORT_DESC, SORT_NUMERIC, $names, SORT_ASC, SORT_STRING, $source)); // doesn't work
print_r($source);
call_user_func_array('array_multisort', array($points, SORT_DESC, SORT_NUMERIC, $names, SORT_ASC, SORT_STRING, &$source)); // works!
print_r($source);

// Call like arrayColumnSort('points', SORT_DESC, SORT_NUMERIC, 'name', SORT_ASC, SORT_STRING, $source);

// Slightly adapted from http://www.php.net/manual/en/function.array-multisort.php#60401

// arrayColumnSort(string $field, [options, ], string $field2, [options, ], .... , $array) /

//____________________
// arrayColumnSort() /
function arrayColumnSort() {
 
$args  = func_get_args();
 
$array = array_pop($args);
  if (!
is_array($array)) return false;
 
// Here we'll sift out the values from the columns we want to sort on, and put them in numbered 'subar' ("sub-array") arrays.
  //   (So when sorting by two fields with two modifiers (sort options) each, this will create $subar0 and $subar3)
 
foreach($array as $key => $row) // loop through source array
   
foreach($args as $akey => $val) // loop through args (fields and modifiers)
     
if(is_string($val))             // if the arg's a field, add its value from the source array to a sub-array
       
${"subar$akey"}[$key] = $row[$val];
 
// $multisort_args contains the arguments that would (/will) go into array_multisort(): sub-arrays, modifiers and the source array
 
$multisort_args = array();
  foreach(
$args as $key => $val)
   
$multisort_args[] = (is_string($val) ? ${"subar$key"} : $val);
 
$multisort_args[] = &$array;   // finally add the source array, by reference
 
call_user_func_array("array_multisort", $multisort_args);
  return
$array;
}

?>
frank at overdrunk dot net 14-Jan-2009 02:38
I had a function to make a sort on a 2D array and I wanted to sort an array using a column that usualy contains numeric values but also strings.

Lets say we have this array :

Array (
  [0] => Array ( "name" = "12000" ),
  [1] => Array ( "name" = "113" ),
  [2] => Array ( "name" = "test 01" ),
  [3] => Array ( "name" = "15000 tests" ),
  [4] => Array ( "name" = "45" ),
  [5] => Array ( "name" = "350" ),
  [6] => Array ( "name" = "725" ),
  [7] => Array ( "name" = "hello" )
}

SORT_STRING whould have returned me this :

Array ( // Numeric values are not correctly sorted
  [0] => Array ( "name" = "113" ),
  [1] => Array ( "name" = "12000" ),
  [2] => Array ( "name" = "15000 tests" ),
  [3] => Array ( "name" = "350" ),
  [4] => Array ( "name" = "45" ),
  [5] => Array ( "name" = "725" ),
  [6] => Array ( "name" = "hello" ),
  [7] => Array ( "name" = "test 01" )
}

SORT_NUMERIC would have returned me this :

Array ( // String values are not sorted, just in the same order
  [0] => Array ( "name" = "test 01" ),
  [1] => Array ( "name" = "hello" ),
  [2] => Array ( "name" = "45" ),
  [3] => Array ( "name" = "113" ),
  [4] => Array ( "name" = "350" ),
  [5] => Array ( "name" = "725" ),
  [6] => Array ( "name" = "12000" ),
  [7] => Array ( "name" = "15000 tests" ),
}

So I've made this hybrid code which combines the best of both worlds by merging content sorted either way according to the first caracter of the string:

<?php
/**
 * Sorts an array according to a specified column
 * Params : array  $table
 *          string $colname
 *          bool   $numeric
 **/
function sort_col($table, $colname) {
 
$tn = $ts = $temp_num = $temp_str = array();
  foreach (
$table as $key => $row) {
    if(
is_numeric(substr($row[$colname], 0, 1))) {
     
$tn[$key] = $row[$colname];
     
$temp_num[$key] = $row;
    }
    else {
     
$ts[$key] = $row[$colname];
     
$temp_str[$key] = $row;
    }
  }
  unset(
$table);

 
array_multisort($tn, SORT_ASC, SORT_NUMERIC, $temp_num);
 
array_multisort($ts, SORT_ASC, SORT_STRING, $temp_str);
  return
array_merge($temp_num, $temp_str);
}
?>

It would return something like this :

Array (
  [2] => Array ( "name" = "45" ),
  [3] => Array ( "name" = "113" ),
  [4] => Array ( "name" = "350" ),
  [5] => Array ( "name" = "725" ),
  [6] => Array ( "name" = "12000" ),
  [7] => Array ( "name" = "15000 tests" ),
  [1] => Array ( "name" = "hello" ),
  [0] => Array ( "name" = "test 01" ),
}
Zbigniew Heintze http://bigweb.pl 26-Nov-2008 11:36
<?php
/**
 * Sort DB result
 *
 * @param array $data Result of sql query as associative array
 *
 * Rest of parameters are optional
 * [, string $name  [, mixed $name or $order  [, mixed $name or $mode]]]
 * $name string - column name i database table
 * $order integer - sorting direction ascending (SORT_ASC) or descending (SORT_DESC)
 * $mode integer - sorting mode (SORT_REGULAR, SORT_STRING, SORT_NUMERIC)
 *
 * <code>
 * <?php
 * // You can sort data by several columns e.g.
 * $data = array();
 * for ($i = 1; $i <= 10; $i++) {
 *     $data[] = array( 'id' => $i,
 *                      'first_name' => sprintf('first_name_%s', rand(1, 9)),
 *                      'last_name' => sprintf('last_name_%s', rand(1, 9)),
 *                      'date' => date('Y-m-d', rand(0, time()))
 *                  );
 * }
 * $data = sortDbResult($data, 'date', SORT_DESC, SORT_NUMERIC, 'id');
 * printf('<pre>%s</pre>', print_r($data, true));
 * $data = sortDbResult($data, 'last_name', SORT_ASC, SORT_STRING, 'first_name', SORT_ASC, SORT_STRING);    
 * printf('<pre>%s</pre>', print_r($data, true));
 * ?>
 * </code>
 *
 * @return array $data - Sorted data
 */
function sortDbResult(array $data /*$name, $order, $mode*/) {
   
$_argList = func_get_args();
   
$_data = array_shift($_argList);
    if (empty(
$_data)) {
        return
$_data;
    }
   
$_max = count($_argList);
   
$_params = array();
   
$_cols = array();
   
$_rules = array();
    for (
$_i = 0; $_i < $_max; $_i += 3)
    {
       
$_name = (string) $_argList[$_i];
        if (!
in_array($_name, array_keys(current($_data)))) {
            continue;
        }
        if (!isset(
$_argList[($_i + 1)]) || is_string($_argList[($_i + 1)])) {
           
$_order = SORT_ASC;
           
$_mode = SORT_REGULAR;
           
$_i -= 2;
        } else if (
3 > $_argList[($_i + 1)]) {
           
$_order = SORT_ASC;
           
$_mode = $_argList[($_i + 1)];
           
$_i--;
        } else {
           
$_order = $_argList[($_i + 1)] == SORT_ASC ? SORT_ASC : SORT_DESC;
            if (!isset(
$_argList[($_i + 2)]) || is_string($_argList[($_i + 2)])) {
               
$_mode = SORT_REGULAR;
               
$_i--;
            } else {
               
$_mode = $_argList[($_i + 2)];
            }
        }
       
$_mode = $_mode != SORT_NUMERIC
                   
? $_argList[($_i + 2)] != SORT_STRING ? SORT_REGULAR : SORT_STRING
                   
: SORT_NUMERIC;
       
$_rules[] = array('name' => $_name, 'order' => $_order, 'mode' => $_mode);
    }
    foreach (
$_data as $_k => $_row) {
        foreach (
$_rules as $_rule) {
            if (!isset(
$_cols[$_rule['name']])) {
               
$_cols[$_rule['name']] = array();
               
$_params[] = &$_cols[$_rule['name']];
               
$_params[] = $_rule['order'];
               
$_params[] = $_rule['mode'];
            }
           
$_cols[$_rule['name']][$_k] = $_row[$_rule['name']];
        }
    }
   
$_params[] = &$_data;
   
call_user_func_array('array_multisort', $_params);
    return
$_data;
}
?>
matt at idizinc dot com 23-Oct-2008 11:47
I looked on some forms for an answer to this simple problem and couldn't find one so I came up with a solution that may help in some situations.

How do you sort an array by a field in that array and resolve numeric ties randomly?

Code:
<?php

foreach($list as $temp_list)
{
  
$sort_aux[] = ($temp_list['column_to_sort_by']+(rand(1, 9)/10));
}
array_multisort($sort_aux, SORT_NUMERIC, $list);

?>

Example:

$list[]=array('name'=>'Tom', 'score'=>3);
$list[]=array('name'=>'Sam', 'score'=>3);
$list[]=array('name'=>'Joey', 'score'=>1);

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

Hope this helps someone.
isp dot php at spspft dot de 19-Oct-2008 05:44
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.

Hope this helps someone
seiffs_at_centrum-dot-cz 18-Aug-2008 08:53
There have to be two corrections to the php_multisort($data,$keys)

    // Sort Expression
    $i=0;
    $sort='';  //here
    foreach ($keys as $k){
      if($i>0){$sort.=',';}
      $sort.='$cols[\''.$k['key'].'\']'; //and here
      if($k['sort']){$sort.=',SORT_'.strtoupper($k['sort']);}
      if($k['type']){$sort.=',SORT_'.strtoupper($k['type']);}
      $i++;
    }
Jon L. -- intel352 [AT] gmail [DOT] com 26-Feb-2007 08:27
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>: <br> <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>: <br> <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
        )

)
brettz9 throu gh yah 14-Sep-2006 12: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"
}
KES http://kes.net.ua 27-Jul-2006 05: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);
?>
scott - evolove - net - work it out 22-Mar-2006 07: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;   
}
--------------------
php a-t-the-r-a-t-e chir.ag 05-Jan-2006 02: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
        )

)
RWC 25-Sep-2005 01: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().
joao at intrasystems dot com dot br 07-Apr-2005 12: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
        )

)
meddle at dzygn.com 05-Oct-2004 07: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
        )

)
PHP8中文手册 站长在线 整理 版权归PHP文档组所有