PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

array_pad> <array_merge
Last updated: Fri, 04 Jul 2008

view this page in

array_multisort

(PHP 4, PHP 5)

array_multisort — Ordena múltiples matrices, o matrices multi-dimensionales

Descripción

bool array_multisort ( array $matriz1 [, mixed $arg [, mixed $... [, array $... ]]] )

Devuelve TRUE si todo se llevó a cabo correctamente, FALSE en caso de fallo.

array_multisort() puede usarse para ordenar varias matrices al tiempo, o una matriz multi-dimensional por una o más dimensiones.

Las llaves asociativas (string) son conservadas, aunque las llaves numéricas son re-indexadas.

Las matrices de entrada son tratadas como columnas de una tabla que deberá ser ordenada por filas - de forma similar a la funcionalidad de una sentencia SQL ORDER BY. La primera matriz es considerada la primaria para el ordenamiento. Las filas (valores) en esa matriz que sean comparadas como iguales son ordenadas por la siguiente matriz de entrada, y así sucesivamente.

La estructura de argumentos de esta función es un poco inusual, pero flexible. El primer argumento debe ser una matriz. Subsecuentemente, cada argumento puede ser o una matriz o una bandera de ordenamiento de las siguientes.

Banderas de orientación del ordenamiento:

  • SORT_ASC - Ordenar ascendentemente
  • SORT_DESC - Ordenar descendentemente

Banderas de tipo de ordenamiento

  • SORT_REGULAR - Comparar elementos normalmente
  • SORT_NUMERIC - Comparar elementos numéricamente
  • SORT_STRING - Comparar elementos como cadenas

No pueden especificarse dos banderas de ordenamiento del mismo tipo luego de cada matriz. Las banderas de ordenamiento especificadas a continuación de un argumento matriz se aplican sólo a esa matriz - estos valores son restablecidos de vuelta a SORT_ASC y SORT_REGULAR antes de cada nuevo argumento matriz.

Example #1 Ordenamiento de varias matrices

<?php
$matriz1 
= array("10"100100"a");
$matriz2 = array(13"2"1);
array_multisort($matriz1$matriz2);

var_dump($matriz1);
var_dump($matriz2);
?>

En este ejemplo, después del ordenamiento, la primera matriz contendrá los valores 10, "a", 100, 100. La segunda matriz contendrá 1, 1, "2", 3. Las entradas en la segunda matriz que correspondían a las entradas idénticas de la primera matriz (100 y 100) fueron ordenadas también.

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

Example #2 Ordenamiento de una matriz multi-dimensional

<?php
$matriz 
= array(
       array(
"10"11100100"a"),
       array(   
1,  2"2",   3,   1)
      );
array_multisort($matriz[0], SORT_ASCSORT_STRING,
                
$matriz[1], SORT_NUMERICSORT_DESC);
var_dump($matriz);
?>

En este ejemplo, después del ordenamiento, la primera matriz se transformará a 10, 100, 100, 11, "a" (fue ordenada como cadenas en orden ascendente), y la segunda tendrá 1, 3, "2", 2, 1 (ordenada como números, en orden descendiente).

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 Ordenamiento de resultados de una base de datos

Para este ejemplo, cada elemento en la matriz datos representa una fila en una tabla. Este tipo de conjunto de datos es típico de los registros en una base de datos.

Datos de ejemplo:

volumen| edicion
-------+--------
    67 |       2
    86 |       1
    85 |       6
    98 |       2
    86 |       6
    67 |       7

Las datos como una matriz, llamada datos. Ésta se obtendría usualmente, por ejemplo, mediante un ciclo con mysql_fetch_assoc().

<?php
$datos
[] = array('volumen' => 67'edicion' => 2);
$datos[] = array('volumen' => 86'edicion' => 1);
$datos[] = array('volumen' => 85'edicion' => 6);
$datos[] = array('volumen' => 98'edicion' => 2);
$datos[] = array('volumen' => 86'edicion' => 6);
$datos[] = array('volumen' => 67'edicion' => 7);
?>

En este ejemplo, ordenaremos por volumen descendientemente, y por edicion ascendentemente.

Tenemos una matriz de filas, pero array_multisort() requiere una matriz de columnas, así que usamos el código a continuación para obtener las columnas, y luego realizar el ordenamiento.

<?php
// Obtener una lista de columnas
foreach ($datos as $llave => $fila) {
    
$volumen[$llave]  = $fila['volumen'];
    
$edicion[$llave] = $fila['edicion'];
}
// Ordenar los datos con volumen descendiente, edicion ascendiente
// Agregar $datos como el último parámetro, para ordenar por la llave común
array_multisort($volumenSORT_DESC$edicionSORT_ASC$datos);
?>

El conjunto de datos está ordenado ahora, y lucirá de este modo:

volumen| edicion
-------+--------
    98 |       2
    86 |       1
    86 |       6
    85 |       6
    67 |       2
    67 |       7

Example #4 Ordenamiento insensible a mayúsculas/minúsculas

Tanto SORT_STRING como SORT_REGULAR son sensibles a mayúsculas/minúsculas, las cadenas que comienzan con una letra mayúscula vendrán antes que las cadenas con una letra minúscula.

Para realizar una búsqueda insensible a minúsculas y mayúsculas, asegúrese de que el orden sea determinado por una copia en minúsculas de la matriz original.

<?php
$matriz 
= array('Alpha''atomico''Beta''banco');
$matriz_minusculas array_map('strtolower'$matriz);

array_multisort($matriz_minusculasSORT_ASCSORT_STRING$matriz);

print_r($matriz);
?>

El resultado del ejemplo seria:

Array
(
    [0] => Alpha
    [1] => atomico
    [2] => banco
    [3] => Beta
)



array_pad> <array_merge
Last updated: Fri, 04 Jul 2008
 
add a note add a note User Contributed Notes
array_multisort
php {dot} net [arrt] sebble.com
11-May-2008 11:16
I was requiring a PHP function a sort my array data as part of an SQL interpreter for PHP arrays. This is the code I came up with. and works wonderfully.

I hope this helps somebody. If anyone uses this, let me know what you think, if there are any problems with it...

<?

##                ##
##  PHPMultiSort  ##
##                ##
// Takes:
//        $data,  multidim array
//        $keys,  array(array(key=>col1, sort=>desc), array(key=>col2, type=>numeric))

function php_multisort($data,$keys){
 
 
 
 
// List As Columns
 
foreach ($data as $key => $row) {
    foreach (
$keys as $k){
     
$cols[$k['key']][$key] = $row[$k['key']];
    }
  }
 
// List original keys
 
$idkeys=array_keys($data);
 
// Sort Expression
 
$i=0;
  foreach (
$keys as $k){
    if(
$i>0){$sort.=',';}
   
$sort.='$cols['.$k['key'].']';
    if(
$k['sort']){$sort.=',SORT_'.strtoupper($k['sort']);}
    if(
$k['type']){$sort.=',SORT_'.strtoupper($k['type']);}
   
$i++;
  }
 
$sort.=',$idkeys';
 
// Sort Funct
 
$sort='array_multisort('.$sort.');';
  eval(
$sort);
 
// Rebuild Full Array
 
foreach($idkeys as $idkey){
   
$result[$idkey]=$data[$idkey];
  }
  return
$result;
}

###############

// Example Data

$_DATA['table1'][] = array("name" => "Sebastian", "age" => 18, "male" => true);
$_DATA['table1'][] = array("name" => "Lawrence""age" => 16, "male" => true);
$_DATA['table1'][] = array("name" => "Olivia",    "age" => 10, "male" => false);
$_DATA['table1'][] = array("name" => "Dad",       "age" => 50, "male" => true);
$_DATA['table1'][] = array("name" => "Mum",       "age" => 40, "male" => false);
$_DATA['table1'][] = array("name" => "Sebastian", "age" => 56, "male" => true);
$_DATA['table1'][] = array("name" => "Lawrence""age" => 19, "male" => true);
$_DATA['table1'][] = array("name" => "Olivia",    "age" => 24, "male" => false);
$_DATA['table1'][] = array("name" => "Dad",       "age" => 10, "male" => true);
$_DATA['table1'][] = array("name" => "Mum",       "age" => 70, "male" => false);

###############

$res=php_multisort($_DATA['table1'], array(array('key'=>'name'),array('key'=>'age','sort'=>'desc')))
var_dump($res);

/*
array(10) {
  [8]=>
  array(3) {
    ["name"]=>
    string(3) "Dad"
    ["age"]=>
    int(10)
    ["male"]=>
    bool(true)
  }
  [3]=>
  array(3) {
    ["name"]=>
    string(3) "Dad"
    ["age"]=>
    int(50)
    ["male"]=>
    bool(true)
  }
  [1]=>
  array(3) {
    ["name"]=>
    string(8) "Lawrence"
    ["age"]=>
    int(16)
    ["male"]=>
    bool(true)
  }
  [6]=>
  array(3) {
    ["name"]=>
    string(8...
*/
?>
slinden at gmail dot com
29-Apr-2008 09:48
this function would actually be very usefull if alphanumeric sorting was possible..
No Spam
23-Apr-2008 12:02
To sort the array returned e.g. by oci_fetch_all you must divide it in seperate arrays.
Example:
<?php
$rows
=oci_fetch_all($stmt,$results);
?>
now you have several arrays each named by the key name in the sql result.
E.g. array of names, array of streets, array of towns.
To sort the result by e.g. towns you would do the following:
<?php
array_multisort
($results[towns],$results[names],$results[streets]);
?>
Done.
To display the result sorted by towns you could use this:
<?php
print_r
(array("names"=>$results[names],"streets"=>$results[streets],
"towns"=>$result[towns]));
?>
joopm at hotmail dot com
10-Apr-2008 01:50
@ scott at bartoncomputer dot com

You could also reference the array (if you wanted the original array in the object sorted):

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

Regards, Chr.
nickl at hamiltontampa dot com
24-Feb-2008 08:02
I believe this should read:

foreach($firstarray as $sortarray){
      $column[] = $sortarray['email'];
}

//sort arrays after loop
array_multisort($column, SORT_ASC, $firstarray);

Otherwise you will get an array is inconsistent err because $column array won't equal $firstarray until the loop completes.

It was the only way I got it to work, then it was fine. If I am wrong please post a correction.
glenn at freebsd dot nl
29-Nov-2007 07:49
To sort a nested array by column (key/index):

Example: two entries in the nested array:

firstarray[0]['adres'] = "adres1"
firstarray[0]['email'] = "email2"

firstarray[1]['adres'] = "adres2"
firstarray[1]['email'] = "email1"

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

Without code: output would put adres1/email2 on top

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

foreach($firstarray as $sortarray)
{
$column[] = $sortarray['email'];
array_multisort($column, SORT_ASC, $firstarray);
}

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

With code: output would put adres2/email1 on top
scott at bartoncomputer dot com
03-May-2007 07:18
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!
10-Apr-2007 12: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 />';

    }

?>
vermon7
27-Feb-2007 10:23
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) ;

?>
Jon L. -- intel352 [AT] gmail [DOT] com
26-Feb-2007 05: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
        )

)
01-Dec-2006 03: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 ...
brettz9 throu gh yah
14-Sep-2006 09: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 02: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 03: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 02: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 02: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 01: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
17-May-2006 06: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, 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.
scott - evolove - net - work it out
23-Mar-2006 04: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 04: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
31-Jan-2006 08: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
05-Jan-2006 11: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
19-Dec-2005 08:36
Notepad's example using asort/arsort will -not- work unless 'points' is defined -before- 'name'.

Running t