|
 |
array_multisort (PHP 4, PHP 5) array_multisort -- Сортировать несколько массивов или многомерные массивы Описаниеbool array_multisort ( array ar1 [, mixed arg [, mixed ... [, array ...]]] )
Функция array_multisort() может быть использована для
сортировки сразу нескольких массивов или одного многомерного массива
в соответствии с одной или несколькими размерностями. Эта функция
сохраняет соответствие между ключами и соответствующими им значениями.
Входные массивы рассматриваются как столбцы таблицы, которую
нужно отсортировать по строкам - такой подход напоминает
поведение выражения SQL ORDER BY. Первый массив имеет
проиоритет в процессе сортировки.
Структура аргументов этой функции немного необычна,
но удобна. Первым аргументом должен быть массив. Последующие
аргументы могут быть как массивами, так и значениями,
определяющими порядок сортировки, приведенными в
нижеследующем списке.
Значения, определяющие порядок сортировки:
Sorting type flags:
SORT_REGULAR - сравнивать элементы обычным образом SORT_NUMERIC - сравнивать элементы, как если бы они были числами SORT_STRING - сравнивать элементы, как если бы они были строками
Недопустимым является указание двух флагов сортировки одинакового типа
после каждого массива. Флаги сортировки, переданные после аргумента
массив, применяются только к этому аргументу -
перед тем, как функция начнет обрабатывать следующий массив, эти флаги
снова принимают значения по умолчаниюt SORT_ASC и SORT_REGULAR.
Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.
Пример 1. Сортировка нескольких массивов
$ar1 = array ("10", 100, 100, "a");
$ar2 = array (1, 3, "2", 1);
array_multisort ($ar1, $ar2);
|
|
В вышеприведенном примере, после того, как будет осуществлена
сортировка, первый массив будет содержать 10, "a", 100, 100.
Второй - 1, 1, "2", 3. Элементы второго массива, соответствующие
идентичным элементам первого (100 и 100), также будут отсортированы.
Пример 2. Сортировка многомерного массива
$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 (элементы отсортированы
как числа, в порядке убывания).
array_multisort
Cesar Sirvent
17-May-2006 09: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
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;
}
--------------------
peter dot graham at tcat dot ac dot uk
16-Feb-2006 07: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 11: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
$test[0]['name'] = "David";
$test[0]['age'] = 28;
$test[1]['name'] = "Dennis";
$test[1]['age'] = 23;
$test[2]['name'] = "Joseph";
$test[2]['age'] = 42;
function sortmddata($array, $by, $order, $type){
$sortby = "sort$by"; $firstval = current($array); $vals = array_keys($firstval); foreach ($vals as $init){
$keyname = "sort$init";
$$keyname = array();
}
foreach ($array as $key => $row) {
foreach ($vals as $names){
$keyname = "sort$names";
$test = array();
$test[$key] = $row[$names];
$$keyname = array_merge($$keyname,$test);
}
}
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);
}
}
return $array;
}
$test = sortmddata($test,'age','ASC','num');
print_r ($test);
?>
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 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); print_r($test2); ?>
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 11: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
09-Dec-2005 04: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);
?>
the above seems to work for me...
Shmee
30-Sep-2005 06: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
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().
AlberT at SuperAlberT dot it
18-Jul-2005 06:59
a nice piece of code to do an "array_key_multi_sort()" is the following:
<?php
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
12-Jun-2005 11: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
25-Apr-2005 09: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 08: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]; 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
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
)
)
Toni
10-Nov-2004 03: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 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
)
)
kat dot n0spam at audiogalaxy dot com
23-Aug-2001 10: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:
bugs.php?id=12936
| |