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);
?>array_multisort
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
array_multisort
Референца за `function.array-multisort.php` со подобрена типографија и навигација.
array_multisort
(PHP 4, PHP 5, PHP 7, PHP 8)
array_multisort — Сортирај повеќе или повеќедимензионални низи
= NULL
array
&$array1,mixed
$array1_sort_order = SORT_ASC,mixed
$array1_sort_flags = SORT_REGULAR,mixed
...$rest): true
array_multisort() може да се користи за сортирање на неколку низи одеднаш, или на повеќедимензионална низа по една или повеќе димензии.
Асоцијативни (string) клучевите ќе бидат задржани, но нумеричките клучеви ќе бидат повторно индексирани.
Забелешка:
Ако два члена се споредат како еднакви, тие го задржуваат својот оригинален редослед. Пред PHP 8.0.0, нивниот релативен редослед во сортираната низа беше недефиниран.
Забелешка:
Ги ресетира внатрешниот покажувач на низата на првиот елемент.
Параметри
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- спореди ставки како низи, врз основа на тековниот локал. Користи го локалот, кој може да се промени со користење на setlocale() -
SORT_NATURAL- спореди ставки како низи користејќи "природно нарачување" како natsort() -
SORT_FLAG_CASE- може да се комбинира (бинарно ИЛИ) соSORT_STRINGorSORT_NATURALза сортирање на низи без разлика на големината на буквите
Овој аргумент може да се замени со
array1_sort_orderили целосно да се изостави, во кој случајSORT_REGULARсе претпоставува. -
rest-
Повеќе низи, опционално проследени со редослед на сортирање и знаменца. Се споредуваат само елементите што одговараат на еквивалентни елементи во претходните низи. Со други зборови, сортирањето е лексикографско.
Вратени вредности
Секогаш враќа true.
Примери
Пример #1 Сортирање на повеќе низи
<?php
$ar1 = array(10, 100, 100, 0);
$ar2 = array(1, 3, 2, 4);
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)
}
Пример #2 Сортирање на повеќедимензионална низа
<?php
$ar = array(
array("10", 11, 100, 100, "a"),
array( 1, 2, "2", 3, 1)
);
array_multisort($ar[0], SORT_ASC, SORT_STRING,
$ar[1], SORT_NUMERIC, SORT_DESC);
var_dump($ar);
?>Во овој пример, по сортирањето, првата низа ќе се трансформира во "10", 100, 100, 11, "a" (беше сортирана како низи по растечки редослед). Втората ќе содржи 1, 3, "2", 2, 1 (сортирани како броеви, по опаѓачки редослед).
array(2) {
[0]=> array(5) {
[0]=> string(2) "10"
[1]=> int(100)
[2]=> int(100)
[3]=> int(11)
[4]=> string(1) "a"
}
[1]=> array(5) {
[0]=> int(1)
[1]=> int(3)
[2]=> string(1) "2"
[3]=> int(2)
[4]=> int(1)
}
}
Example #3 Sorting database results
For this example, each element in the data array represents one row in a table. This type of dataset is typical of database records.
Пример #3 Сортирање на резултати од базата на податоци
volume | edition
-------+--------
67 | 2
86 | 1
85 | 6
98 | 2
86 | 6
67 | 7
За овој пример, секој елемент во dataнизата претставува еден ред во табела. Овој тип на податоци е типичен за записи од базата на податоци. mysqli_fetch_assoc().
Примерни податоци: volume Податоците како низа, наречена edition ascending.
. Ова обично, на пример, би се добило со циклус со array_multisort() Во овој пример, ќе сортираме по
<?php
// The data as created by looping over mysqli_fetch_assoc:
$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);
// Obtain a list of columns
foreach ($data as $key => $row) {
$volume[$key] = $row['volume'];
$edition[$key] = $row['edition'];
}
// You can use array_column() instead of the above code
$volume = array_column($data, 'volume');
$edition = array_column($data, 'edition');
// Sort the data with volume descending, edition ascending
// Add $data as the last parameter, to sort by the common key
array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);
// Loop over the data and output the sorted values for each column
echo 'volume | edition', PHP_EOL;
echo '-------+--------', PHP_EOL;
for ($i = 0; $i < count($data); $i++) {
printf("%6d | %7d\n", $volume[$i], $edition[$i]);
}
?>опаѓачки,
volume | edition
-------+--------
98 | 2
86 | 1
86 | 6
85 | 6
67 | 2
67 | 7
Имаме низа од редови, но
И двете SORT_STRING and
SORT_REGULAR бара низа од колони, па ја користиме подолу дадената шифра за да ги добиеме колоните, а потоа да го извршиме сортирањето.
Податоците се сега сортирани и ќе изгледаат вака:
<?php
$array = array('Alpha', 'atomic', 'Beta', 'bank');
$array_lowercase = array_map('strtolower', $array);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $array);
print_r($array);
?>Пример #1 Пример што покажува затворачка ознака што го опфаќа последниот нов ред
Array
(
[0] => Alpha
[1] => atomic
[2] => bank
[3] => Beta
)
Види Исто така
- usort() - Сортирај низа по вредности користејќи кориснички дефинирана функција за споредба
- На споредба на функции за сортирање на списоци
Белешки од корисници 8 белешки
One-liner function to sort multidimensionnal array by key, thank's to array_column
<?php
array_multisort (array_column($array, 'key'), SORT_DESC, $array);
?>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;
}
?>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);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!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"
}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.Be aware with array_multisort() and array_column() when you don't want to sort all columns. The last arg ...$rest is used to sort too!
<?php
$data = [
['id' => 5, 'name' => 'Marie'],
['id' => 7, 'name' => 'Lisa'],
['id' => 4, 'name' => 'Marie'],
['id' => 3, 'name' => 'Jean'],
['id' => 1, 'name' => 'Marie'],
['id' => 2, 'name' => 'Jean'],
];
array_multisort(
array_column($data, 'name'), SORT_ASC, SORT_REGULAR,
$data,
);
/*
We could guess :
3 Jean
2 Jean
7 Lisa
5 Marie
4 Marie
1 Marie
But the result is :
2 Jean
3 Jean
7 Lisa
1 Marie
4 Marie
5 Marie
... id column has been sorted too!
*/