Hướng dẫn dùng array multisort trong PHP

  • Trang chủ
  • Phát triển web
  • PHP
  • Hàm array_multisort[] trong PHP

Hướng dẫn cách sử dụng hàm array_multisort[] về mảng trong lập trình PHP

Tác dụng của hàm array_multisort[]

The array_multisort[] function sort multiple arrays at once, or a multi-dimensional array by one or more dimensions. The sorting is done as though the arrays were columns in a table.

Associative or string keys will be preserved, but numeric keys will be re-indexed.

The following table summarizes the technical details of this function.

Return Value:Changelog:Version:
Returns TRUE on success or FALSE on failure.

The sort flags SORT_NATURAL and SORT_FLAG_CASE were added in PHP 5.4.0

The sort flag SORT_LOCALE_STRING was added in PHP 5.3.0

PHP 4+

Syntax

The basic syntax of the array_multisort[] function is given with:

array_multisort[array1, array1_sort_order, array1_sort_flags, ...]

The following example shows the array_multisort[] function in action.

Tip: The first array is the main one to sort by; all items in the other arrays are reordered based on the sorted order of the first array [i.e., arrays are treated as columns of a table]. If items in the first array compare as equal, the sort order is determined by the second array, and so on.

In the above example after sorting, the first array will contain 2, 5, 7, 10, the second array will contain 4, 2, 3, 1. Notice that the entries in the second array corresponds to the entries in the first array. To better understand this, let's take a closer look at the following illustration.

     array1 | array2
    --------+--------
        2   |      4
        7   |      3
        10  |      1
        5   |      2
 
 array1 | array2
--------+--------
    2   |      4
    5   |      2
    7   |      3
    10  |      1
     Before Sorting    After Sorting

Parameters

The array_multisort[] function accepts the following parameters.

ParameterDescription
array1 Required. Specifies the array to sort.
array1_sort_order

Optional. Specifies the sorting order. Possible values are:

  • SORT_ASC – Sort in ascending order [A-Z]. Default value.
  • SORT_DESC – Sort in descending order [Z-A].
array1_sort_flags

Optional. Specifies how array items should be compared. Possible values are:

  • SORT_REGULAR – Compare items normally [don't change types]. Default value.
  • SORT_NUMERIC – Compare items numerically.
  • SORT_STRING – Compare items as strings.
  • SORT_LOCALE_STRING – Compare items as strings, based on the current locale.
  • SORT_NATURAL – Compare items as strings using "natural ordering" algorithm, like the PHP natsort[] function.
  • SORT_FLAG_CASE – Can be combined [bitwise OR] with SORT_STRING or SORT_NATURAL to sort strings case-insensitively.
... Optional. Specifies more arrays to sort, optionally followed by sort order and flags. Only elements corresponding to equivalent elements in previous arrays are compared.

More Examples

Here're some more examples showing how array_multisort[] function basically works:

The following example shows how to sort a multi-dimensional array with this function.

Bài viết này đã giúp ích cho bạn?

Bài viết mới

[PHP 4, PHP 5, PHP 7, PHP 8]

array_multisortSort multiple or multi-dimensional arrays

Description

array_multisort[
    array &$array1,
    mixed $array1_sort_order = SORT_ASC,
    mixed $array1_sort_flags = SORT_REGULAR,
    mixed ...$rest
]: bool

Associative [string] keys will be maintained, but numeric keys will be re-indexed.

Note:

If two members compare as equal, they retain their original order. Prior to PHP 8.0.0, their relative order in the sorted array was undefined.

Note:

Resets array's internal pointer to the first element.

Parameters

array1

An array being sorted.

array1_sort_order

The order used to sort the previous array argument. Either SORT_ASC to sort ascendingly or SORT_DESC to sort descendingly.

This argument can be swapped with array1_sort_flags or omitted entirely, in which case SORT_ASC is assumed.

array1_sort_flags

Sort options for the previous array argument:

Sorting type flags:

  • SORT_REGULAR - compare items normally [don't change types]
  • SORT_NUMERIC - compare items numerically
  • SORT_STRING - compare items as strings
  • SORT_LOCALE_STRING - compare items as strings, based on the current locale. It uses the locale, which can be changed using setlocale[]
  • SORT_NATURAL - compare items as strings using "natural ordering" like natsort[]
  • SORT_FLAG_CASE - can be combined [bitwise OR] with SORT_STRING or SORT_NATURAL to sort strings case-insensitively

This argument can be swapped with array1_sort_order or omitted entirely, in which case SORT_REGULAR is assumed.

rest

More arrays, optionally followed by sort order and flags. Only elements corresponding to equivalent elements in previous arrays are compared. In other words, the sort is lexicographical.

Return Values

Returns true on success or false on failure.

Examples

Example #1 Sorting multiple arrays

In this example, after sorting, the first array will contain 0, 10, 100, 100. The second array will contain 4, 1, 2, 3. The entries in the second array corresponding to the identical entries in the first array [100 and 100] were sorted as well.

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 Sorting multi-dimensional array

In this example, after sorting, the first array will transform to "10", 100, 100, 11, "a" [it was sorted as strings in ascending order]. The second will contain 1, 3, "2", 2, 1 [sorted as numbers, in descending order].

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.

Example data:

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

The data as an array, called data. This would usually, for example, be obtained by looping with mysqli_fetch_assoc[].

In this example, we will order by volume descending, edition ascending.

We have an array of rows, but array_multisort[] requires an array of columns, so we use the below code to obtain the columns, then perform the sorting.

The dataset is now sorted, and will look like this:

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

Example #4 Case insensitive sorting

Both SORT_STRING and SORT_REGULAR are case sensitive, strings starting with a capital letter will come before strings starting with a lowercase letter.

To perform a case insensitive sort, force the sorting order to be determined by a lowercase copy of the original array.

The above example will output:

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

See Also

  • usort[] - Sort an array by values using a user-defined comparison function
  • The comparison of array sorting functions

jimpoz at jimpoz dot com

11 years ago

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[].



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

matt at bosc dot io

6 years ago

One-liner function to sort multidimensionnal array by key, thank's to array_column

cagret at gmail dot com

13 years ago

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:

Robert C

8 years ago

Hi,

I would like to see the next code snippet to be added to //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];

nick [[AT]] nickyost [[DOT]] com

10 years ago

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:



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!

lingtalfi

1 year ago

For database like sorting, here is my 2 cents:



Use it like this:



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

zequez at gmail dot com

12 years ago

Easiest way I find out to sort an entire multidimensional array by one element of it:



^-^

frank at overdrunk dot net

13 years ago

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:



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" ],
}

RWC

16 years ago

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[].

Magento-User

8 years ago

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:

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.

alexander dot v at zend dot com

12 years ago

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:



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:



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:

scott - evolove - net - work it out

16 years ago

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

mech.cx

13 years ago

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" [//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.

Chủ Đề