PHP Conference Japan 2024

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 ...$rest
): bool

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 參數的排序選項

排序型別標誌

此參數可以與 array1_sort_order 交換,或完全省略,在這種情況下會假設為 SORT_REGULAR

rest

更多陣列,選擇性地後面跟著排序順序和標誌。只會比較前一個陣列中對應元素的元素。換句話說,排序是字典順序的。

回傳值

成功時回傳 true,失敗時回傳 false

範例

範例 #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)
  }
}

範例 #3 排序資料庫結果

在這個範例中,data 陣列中的每個元素都代表表格中的一列。這種資料集是資料庫記錄的典型範例。

範例資料

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

資料以陣列形式呈現,稱為 data。通常,例如,會使用 mysqli_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'];
}

// 你可以使用 array_column() 來取代上面的程式碼
$volume = array_column($data, 'volume');
$edition = array_column($data, 'edition');

// 依照 volume 遞減,edition 遞增的方式排序資料
// 將 $data 作為最後一個參數加入,以根據通用鍵排序
array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);
?>

資料集現在已排序,會看起來像這樣

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

範例 #4 不區分大小寫排序

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

上述範例將會輸出

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

另請參閱

新增註解

使用者貢獻的註解 42 個註解

jimpoz at jimpoz dot com
14 年前
我想出了一個簡單的方法來排序資料庫樣式的結果。這會執行範例 3 的操作,只是它會在將控制權傳遞給 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);
}
?>

已排序的陣列現在位於函式的傳回值中,而不是以參考方式傳遞。

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

// 傳遞陣列,接著是欄位名稱和排序旗標
$sorted = array_orderby($data, 'volume', SORT_DESC, 'edition', SORT_ASC);
?>
matt at bosc dot io
8 年前
使用 array_column 依鍵排序多維陣列的單行函式

<?php

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

?>
cagret at gmail dot com
15 年前
一種更直覺的方式,只用一行程式碼使用 array_msort() 排序多維陣列,您不必將原始陣列分成每個欄位的陣列

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

}

?>
Robert C
10 年前
嗨,

我希望看到接下來的程式碼片段被添加到 http://nl3.php.net/array_multisort

目的:依據某些鍵值對二維陣列進行排序

此函數的優點
- 使用 PHP 的 array_multisort 函數進行排序;
- 它為您準備 array_multisort 所需的陣列;
- 允許將排序條件作為單獨的陣列傳遞(可以使用排序順序和標誌);
- 輕鬆設定/覆寫字串的排序方式(不區分大小寫,而不是 PHP 預設的區分大小寫排序方式);
- 效能優異

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

用法

// 使用隨機測試資料填入陣列
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) );

// 設定排序條件(根據需要添加任意多個欄位)
$sortCriteria =
array('field1' => array(SORT_DESC, SORT_NUMERIC),
'field3' => array(SORT_DESC, SORT_NUMERIC)
);

// 像這樣呼叫它
$sortedData = MultiSort($data, $sortCriteria, true);
nick ([AT]) nickyost ([DOT]) com
13 年前
透過在自訂排序函數中使用個別值,USort 函數可以用於排序多維陣列,幾乎不需要任何額外的工作。

即使子元素不是字串,此函數也會傳遞整個子元素。如果它是陣列(如多維陣列中的情況),它會將整個子陣列作為一個參數傳遞。

因此,可以像這樣做一些優雅的事情

<?php
// 排序多維陣列
usort($results, "custom_sort");
// 定義自訂排序函數
function custom_sort($a,$b) {
return
$a['some_sub_var']>$b['some_sub_var'];
}
?>

其他函數需要 40 到 50 行才能完成的事情,此方法只需 4 行程式碼即可完成。此方法不需要您建立暫存陣列或任何其他東西。對我來說,這是一個比這個函數更受歡迎的解決方案。

希望對您有所幫助!
frank at overdrunk dot net
15 年前
我有一個函數可以對二維陣列進行排序,我想要使用一個通常包含數值但有時也包含字串的欄位來排序陣列。

假設我們有這個陣列

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 會傳回我這個結果

陣列 ( // 數值排序不正確)
[0] => 陣列 ( "name" = "113" ),
[1] => 陣列 ( "name" = "12000" ),
[2] => 陣列 ( "name" = "15000 tests" ),
[3] => 陣列 ( "name" = "350" ),
[4] => Array ( "name" = "45" ),
[5] => 陣列 ( "name" = "725" ),
[6] => 陣列 ( "name" = "hello" ),
[7] => 陣列 ( "name" = "test 01" )
}

如果使用 SORT_NUMERIC 會回傳這個

陣列 ( // 字串值沒有排序,只是保持原順序)
[0] => 陣列 ( "name" = "test 01" ),
[1] => 陣列 ( "name" = "hello" ),
[2] => 陣列 ( "name" = "45" ),
[3] => 陣列 ( "name" = "113" ),
[4] => 陣列 ( "name" = "350" ),
[5] => 陣列 ( "name" = "725" ),
[6] => 陣列 ( "name" = "12000" ),
[7] => 陣列 ( "name" = "15000 tests" ),
}

所以我寫了這個混合程式碼,它結合了兩種方式的優點,根據字串的第一個字元來合併排序後的內容。

<?php
/**
* 根據指定的欄位排序陣列
* 參數: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);
}
?>

它會回傳像這樣的結果

Array (
[2] => 陣列 ( "name" = "45" ),
[3] => 陣列 ( "name" = "113" ),
[4] => 陣列 ( "name" = "350" ),
[5] => 陣列 ( "name" = "725" ),
[6] => 陣列 ( "name" = "12000" ),
[7] => 陣列 ( "name" = "15000 tests" ),
[1] => 陣列 ( "name" = "hello" ),
[0] => 陣列 ( "name" = "test 01" ),
}
lingtalfi
3 年前
對於資料庫的排序,這是我的淺見

<?php
/**
* RowsSortHelperTool 類別。
*/
class RowsSortHelperTool
{

/**
* 根據給定的排序方式來排序給定的陣列。
*
* sorts 參數是一個 field => direction 的陣列,
*
* 其中:
*
* - field: 字串,用於排序行的屬性名稱
* - direction: 字串 (asc|desc),排序的方向
*
*
* @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);
}
}

?>

這樣使用它

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

?>

將會顯示像這樣的結果

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
14 年前
我發現最簡單的方法是根據多維陣列的其中一個元素來排序整個陣列

<?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/>";

/* 輸出結果
Abcd
Bcde
Cdef
Defg
*/
?>

^-^
RWC
19 年前
這是 AlberT 的函數的較簡單版本。

很多時候你會得到像這樣的陣列

$test[0]['name']='Peter';
$test[0]['points']=1;

$test[1]['name']='Mike';
$test[1]['points']=5;

$test[2]['name']='John';
$test[2]['points']=2;

你只想根據第二維的索引來排序,也就是上述範例中的 points。

你可以使用下面的函數並這樣呼叫它

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

注意:為了在 compare 函數中使用 $key,它不能簡單地作為參數傳遞。它必須宣告為全域變數並在 compare() 外部的某處設定。
faugeron dot loic at gmail dot com
8 年前
改進範例 #3 (排序資料庫結果):使用 <?php array_column ?> (PHP >= 5.5) 和 <?php call_user_func_array ?> 可以建立你的排序方式(根據一個或多個欄位排序)

<?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 現在會依 ID 降序排序。
?>
nospam at nospam dot com
9 年前
一個超簡單的方式來排序帶鍵值的多維陣列,同時保留所有關聯鍵,包括數值鍵!

如果排序的值相等,則保留原始多維陣列的順序。

<?php
// 依子陣列的值排序多維陣列,同時保留所有鍵,當排序值匹配時也保留原始順序
function maSort($ma = '', $sortkey = '', $sortorder = 1) { // sortorder: 1=asc, 2=desc
if ($ma && is_array($ma) && $sortkey) { // 確認輸入
foreach ($ma as $k=>$a) $temp["$a[$sortkey]"][$k] = $a; // 使用排序值建立臨時多維陣列,為了處理數值浮點數,使用引號將鍵值轉換為字串
if ($sortorder == 2) { // 降序
krsort($temp);
} else {
// 升序
ksort($temp);
}
$newma = array(); // 空的輸出多維陣列,用來加入資料
foreach ($temp as $sma) $newma += $sma; // 將排序後的陣列加入輸出陣列
unset($ma, $sma, $temp); // 釋放記憶體
return $newma;
}
}
?>
brettz9 throu gh yah
18 年前
通常,人們可能會有一組陣列,其中包含需要彼此關聯的平行資料(例如,一組元素的各種屬性值可能儲存在它們自己的陣列中)。 透過指定額外的欄位,如同以下引用的文檔範例,使用 array_multisort 時可能會遺失這種關聯性。

採用文檔中的這個範例資料集
<?php
$ar1
= array("10", 100, 100, "a");
$ar2 = array(1, 3, "2", 1);
?>

範例繼續以這種方式對其進行排序
<?php
array_multisort
($ar1, $ar2);
?>

在這種情況下,儘管 "10" 在排序後仍與第一個 '1' 關聯,但 "2" 和 '3' 會從它們的原始順序反轉。

為了僅按一個欄位排序(但仍讓其他陣列也相應地排序),可以使用 array_keys(從鍵建立一個陣列)來確保不會執行進一步的子排序。 這個方法之所以可行,是因為 array_keys 建立的陣列不會存在重複的鍵(因為鍵是唯一的),因此,後續欄位將與子排序無關。

因此,使用上面的資料,我們可以執行此排序代替
<?php
$ar3
= array_keys($ar1);
array_multisort($ar1, $ar3, $ar2);
?>

當 $ar1 和 $ar2 被輸出時,會得到

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"
}
m dot michalczyk at gmail dot com
15 年前
這是一個基於 za at byza dot it 解決方案的有用範例,用於按任何維度排序多維物件。
za at byza dot it
<?php
/* 範例結構 */
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);

/* 來源 */

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");
}
?>
Magento-User
11 年前
當排序一個(複雜的)物件陣列時,如果較早的元素比較相等,此函數會直接比較後續陣列中的元素,而導致「致命錯誤:巢狀層級太深」。可以使用旗標參數來解決這個問題。
<?php
$sortKeys
= array_map($extractKey, $lotsOfComplexObjects);
array_multisort($sortKeys, $lotsOfComplexObjects, SORT_ASC, SORT_NUMERIC);
?>
我正在替換一個 'uasort()' 呼叫,因為它會導致大量對比較函數的呼叫,而且大多數涉及的物件都是遞迴的,所以速度明顯較慢。

如果這個「技巧」給出錯誤的順序,你需要一個更好的鍵。
Patrick Adrichem
11 年前
如果你尚未安裝 PHP 5.4,且無法使用 SORT_NATURAL。此函數會根據鍵值對陣列進行自然的多維排序。

此函數可用於以下形式的陣列:

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


array( name => value )。

不支援 array( name => array( key => value), name => value) 形式的陣列。

<?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);
}
}
?>
jcharpentier at darkmira dot fr
10 年前
第二個範例缺少精確性

範例 #2 排序多維陣列

說明是
「在這個範例中,[...] 第二個將包含 1、3、"2"、2、1(依數字降序排序)。」
這可能會被誤解,因為依數字降序排序會是 1、1、"2"、2、3。

我的建議如下(用最好的英文表達會更好 ^^)
「在這個範例中,[...] 第二個將包含 1、3、"2"、2、1(排序方式與第一個相同,除了將值 3 和 "2" 依數字降序排序)。因為它們對應於第一個陣列中無法第一次排序的相同條目(100 和 100)。」
alexander dot v at zend dot com
14 年前
array_multisort 在 PHP 5.3 中正常運作,但它強制參數必須為參考。

這對於常見的 array_multisort() 用法沒有影響,但對於需要排序可變數量的陣列,且涉及到 call_user_func_array() 函數的情況,就會產生「問題」。

因此,所有用於排序的陣列都必須被收集到一個新的陣列中,作為對陣列變數的參考。

<?php
$sortArgs
= array();

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

call_user_func_array('array_multisort', $sortArgs);
?>

這個(要求參數必須為參考)實際上並不是一個問題,因為否則來源陣列不會被排序。

重要提示!
如果你在每次處理 array_multisort() 參數的迭代中都使用 $valuesArray 變數,別忘了銷毀它。
如果你不這麼做,所有 array_multisort() 的參數都會包含相同的陣列。

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

最後一件重要的事情 :)
將排序陣列收集到某處。當 $valuesArray 被銷毀時,PHP 5.3 會將參考轉換為值,否則你將再次收到「Parameter 1 to array_multisort() expected to be a reference, value given」的警告。

最終程式碼應該看起來像這樣

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

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

call_user_func_array('array_multisort', $sortArgs);
?>
mech.cx
15 年前
我(和這裡幾乎所有人一樣 :-))正在尋找按關聯子陣列中的特定欄位對二維陣列進行排序的方法。
我不喜歡文件範例的地方在於,你需要先循環遍歷輸入陣列來建立子陣列,然後在函數呼叫中使用這些子陣列。

"php a-t-the-r-a-t-e chir.ag" (https://php.dev.org.tw/manual/en/function.array-multisort.php#60401) 編寫了一個非常巧妙的包裝函數,我稍微重寫了一下,更改了變數名稱並添加了註解(主要是為了我自己著想 :-))。
我發現的一個問題:輸入陣列作為最後一個參數傳遞給 array_multisort,但更改後的陣列並不是返回的陣列。通過參考傳遞它解決了這個問題。這似乎是由於整個事情都位於 call_user_func_array 中,如下所示。

<?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 https://php.dev.org.tw/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;
}

?>
Anonymous
4 個月前
PHP 中的陣列是「有序映射」。這個「順序」是內部的,與鍵的數值無關。
Array_multisort() 似乎是基於這個內部順序進行排序。它不會維護數字鍵的關聯性,然後根據這種關聯性重新編號。它會維護內部順序關聯性,並且數字鍵會根據這種關聯性重新編號。字串鍵不會維護鍵的關聯性或內部順序關聯性,至少在與數字鍵混合使用時是這樣。
換句話說,你的兩個陣列必須以類似的方式建立,否則可能會得到意想不到的結果。

<?php
$foo
=array("foo"=>"fazz", 7, 5,"sing"=>"soft", 9, 2, 0,"fing"=>"fong", 8, 1, 4);
$bar=array("bar"=>"bazz",17,45,"sing"=>"loud",29,72,90,"bing"=>"bong",38,81,54);
array_multisort($foo, $bar);
echo
var_dump($foo),"<br><br>",var_dump($bar),"<br><br>";
?>
array(11) { [0]=> int(0) [1]=> int(1) [2]=> int(2) [3]=> int(4) [4]=> int(5) [5]=> int(7) [6]=> int(8) [7]=> int(9) ["foo"]=> string(4) "fazz" ["fing"]=> string(4) "fong" ["sing"]=> string(4) "soft" }

array(11) { [0]=> int(90) [1]=> int(81) [2]=> int(72) [3]=> int(54) [4]=> int(45) [5]=> int(17) [6]=> int(38) [7]=> int(29) ["bar"]=> string(4) "bazz" ["bing"]=> string(4) "bong" ["sing"]=> string(4) "loud" }

<?php
$foo
=array("foo"=>"fazz", 7, 5,"sing"=>"soft", 9, 2, 0,"fing"=>"fong", 8, 1, 4);
$bar=array(17,45,29,72,90,"sing"=>"loud",38,81,54,"bing"=>"bong","bar"=>"bazz");
array_multisort($foo, $bar);
echo
var_dump($foo),"<br><br>",var_dump($bar),"<br><br>";
?>
array(11) { [0]=> int(0) [1]=> int(1) [2]=> int(2) [3]=> int(4) [4]=> int(5) [5]=> int(7) [6]=> int(8) [7]=> int(9) ["foo"]=> string(4) "fazz" ["fing"]=> string(4) "fong" ["sing"]=> string(4) "soft" }

array(11) { [0]=> int(38) ["bar"]=> string(4) "bazz" ["sing"]=> string(4) "loud" ["bing"]=> string(4) "bong" [1]=> int(29) [2]=> int(45) [3]=> int(54) [4]=> int(90) [5]=> int(17) [6]=> int(81) [7]=> int(72) }

我的專案中的陣列是使用迴圈中的 <?php $foo[]=$filename ?> 語法建立的,如果在迴圈中找到目錄名稱,則會在迴圈內的隨機位置新增一個字串鍵屬性來儲存目錄名稱,同時建立一個相符的陣列,其中包含完整檔案路徑,但不包含目錄資訊。即使在事後為檔案路徑陣列新增一個「假的」相符字串鍵屬性,也無法使用 Array_multisort 來依照檔名排序這兩個陣列。
我必須在另一個變數中建立我的檔案路徑陣列,進行排序,然後在事後將其作為字串鍵屬性新增至檔名陣列。
Sbastien
1 年前
對於多維和/或自訂排序,穿梭運算子 (shuttle operator) 可以是 array_multisort() 的一個聰明替代方案。

<?php

$data
= [
[
'name' => 'John Smith', 'status' => 'Offline'],
[
'name' => 'Anne Onyme', 'status' => 'Online'],
[
'name' => 'Alan Smithee', 'status' => 'Online'],
];

// 先線上,然後依姓名字母順序排序
usort($data, fn ($a, $b) => [
[
'Online' => 1, 'Offline' => 2][$a['status']],
$a['name'],
] <=> [
[
'Online' => 1, 'Offline' => 2][$b['status']],
$b['name'],
]);

print_r($data);

/*
Array
[0] => Array
[name] => Alan Smithee
[status] => Online
[1] => Array
[name] => Anne Onyme
[status] => Online
[2] => Array
[name] => John Smith
[status] => Offline
*/
498936940 at qq dot com
3 年前
根據多個鍵任意排序二維陣列

```
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
);
```
Hayley Watson
6 年前
array_multisort() 的輕量封裝器,以便在排序關聯陣列的陣列時,您可以透過名稱指定要排序的欄位,而不必將它們提取為明確的陣列。請注意,您也可以排序數字索引的欄位,前提是您先將索引轉換為字串(否則它們會與 SORT_* 常數混淆)。

<?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));
}
?>
scott - evolove - net - work it out
18 年前
根據某個值排序關聯陣列的陣列的一個非常簡單的方法是使用 usort。

我需要根據它們的「距離」值排序 20 個資料結構的陣列

陣列
(
[0] => 陣列
(
[blahblah] => blahblah
[distance] => 6
)

[1] => 陣列
(
你懂的....

以下是程式碼

--------------------
usort($results, "distributor_compare");

/**
* usort 回呼
*/
function distributor_compare($a, $b) {
$adist = intval($a['distance']);
$bdist = intval($b['distance']);

if ($adist == $bdist) {
return 0;
}
return ($adist < $bdist) ? -1 : 1;
}
--------------------
ArkieGuy
6 年前
<?php

/**
* array_multisort 的包裝函式 -- 依據鍵值陣列排序資料陣列
*
* $data : 這是要排序的多維陣列
* $keys : 包含 "Key" 欄位名稱和可選的排序/標記的陣列。
*
* 範例:$keys[2] = [ 'Animal', SORT_DESC, SORT_REGULAR | SORT_FLAG_CASE ];
* $keys[1] = [ 'Name' ];
*
* 語法:if( multiSort( $data, $keys ) ) print_r( $data );
*
* 成功時返回 TRUE,失敗時返回 FALSE。
*/
function multiSort( &$data, $keys ) {

// 排序鍵值 - 這允許不按順序傳入鍵值陣列
ksort( $keys );

// 走訪鍵值陣列,建構要傳遞給 call_user_function 的參數
// (必須以 0-n 索引,其中 n 是要排序的資料)
foreach( $keys as $key ) {
// 走訪鍵值參數列表
foreach( $key as $element => $value )
if(
$element == 0 )
// 新增一個包含指定 $data 欄位的欄位值的陣列
$args[] = array_column( $data, $value );
else
// 新增為排序/標記傳入的整數值
// 注意:如果您嘗試將字串值(例如來自 INI)傳送給
// array_multisort 作為 sort_order 或 sort_flags,您會收到
// "Argument #x is expected to be an array or a sort flag"。
// 強制轉換為 int 可以解決這個問題
$args[] = (int)$value;
}

// 將要排序的陣列新增到參數列表
$args[] = &$data;

// 呼叫 array_multisort 以依鍵值順序排序陣列
return( call_user_func_array( 'array_multisort', $args ) );
}

/* 範例 */

echo "<PRE>";

// 資料陣列(可以是關聯陣列或您可以使用欄位編號)
$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'],
];

// 包含 "鍵值" 的陣列 - 每個鍵值都是欄位名稱和
// 可選的排序順序和/或排序標記
// 將先依 Name 排序,然後依 Animal 排序,因為在使用前會先對鍵值陣列進行鍵值排序。
$keys[2] = [ 'Animal', SORT_DESC, SORT_REGULAR | SORT_FLAG_CASE ];
$keys[1] = [ 'Name' ];

//呼叫包裝函式
if( ! multiSort( $data, $keys ) )
die(
'排序失敗' );

print_r( $data );
?>
walterquez at gmail dot com
6 年前
要排序簡單的多維陣列,請使用陣列本身作為修飾符。這將根據第一欄排序。無需編寫自訂函式。

$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);
qasastechnology at gmail dot com
5 年前
不區分大小寫的排序
要執行不區分大小寫的排序

$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;
}
matt at wennersten dot org
9 年前
許多使用者提供了用於泛化 array_multisort 的精巧包裝函式。但是,我們有些人可能只是想要一個簡單的範例,說明如何根據指定欄位排序任意多維陣列,例如資料庫結果集。

考慮一個儲存在檔案系統上並透過資料庫表格引用的語音錄音(Clip 物件)陣列

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

//我們現在有一個名為 clips[] 的陣列,看起來像這樣

array("speaker"=>"Obama","duration"=>"22:00","clip"=>...<一些任意物件>...);

//假設我們想要依 speaker 排序陣列
$sortkeyname = "speaker";
//執行排序
$sortkeyarray = array();
foreach ($clips as $key => $row){
$sortkeyarray[$key] = $row[$sortkeyname];
}
array_multisort($sortkeyarray, SORT_DESC, $clips);

//假設我們想要依 duration 排序陣列
$sortkeyname = "duration";
//執行排序
$sortkeyarray = array();
foreach ($clips as $key => $row){
$sortkeyarray[$key] = $row[$sortkeyname];
}
array_multisort($sortkeyarray, SORT_DESC, $clips);

...等等。
plugboard at web dot de
12 年前
多重排序物件陣列

物件範例 [$包含物件陣列的物件]: (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
)
)
)

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

簡單的 PHP 函式:sort_arr_of_obj()

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

/*
* -------- 函式參數 --------
* $array ........ 物件陣列
* $sortby ....... 要排序的物件鍵值
* $direction ... 'asc' = 遞增
* --------
*/

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;

}


// --------------------------------------
?>

呼叫範例
----------------------------------

<?php

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

?>

結果範例:$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
)

)
)

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

:)
info at ichier dot de
13 年前
如果您想按欄排序陣列,這個函式可以做到。

<?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
13 年前
// 一種使用這種結構來排序陣列的非常簡單的方法。

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

?>

// 排序後的陣列結果

陣列
(
[0] => 陣列
(
[NUMCIE] => 001
[REF] => RHQ
[COLOR] => RED
[L1] => 4
)

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

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

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

)
Jaak Tamre
13 年前
我遇到了一個排序 SimpleXMLElement 列表的問題。我找到了一個不錯的簡短解決方案。

我有一個票券物件的陣列:$ticketList = $xml->Tickets;

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

只需建立一個您想要排序的物件項目陣列,以及一個新的陣列,該陣列將像第一個陣列一樣重新排序。

附註:我自己的 parseDate(date) 會針對不同的日期格式回傳 Unix 時間戳記。
Zbigniew Heintze http://bigweb.pl
16 年前
<?php
/**
* 排序資料庫結果
*
* @param array $data SQL 查詢的結果,以關聯陣列形式呈現
*
* 其餘參數為選用
* [, string $name [, mixed $name 或 $order [, mixed $name 或 $mode]]]
* $name string - 資料庫表格中的欄位名稱
* $order integer - 排序方向,遞增 (SORT_ASC) 或遞減 (SORT_DESC)
* $mode integer - 排序模式 (SORT_REGULAR, SORT_STRING, SORT_NUMERIC)
*
* <code>
* <?php
* // 您可以依多個欄位排序資料,例如:
* $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 - 已排序的資料
*/
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
16 年前
我查閱了一些論壇,想找到這個簡單問題的答案,但都找不到,所以我提出了一個可能在某些情況下有幫助的解決方案。

如何根據陣列中的某個欄位排序陣列,並隨機解決數值上的平手?

程式碼
<?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);

?>

範例

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

說明
我採用了上面找到的一個現有範例,該範例展示了如何根據陣列的其中一個欄位/欄排序陣列。
我只是加入了:"+(rand(1,9)/10)",以隨機將 .1 到 .9 加到他們的分數,以解決平手。(顯然,這個特定範例僅在您依整數排序時才有效...因此您可能需要修改它以滿足您的需求。)

希望這對某些人有幫助。
isp dot php at spspft dot de
16 年前
我想報告一個因訊息而引起的混淆

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...(警告:呼叫時傳址已被棄用;如果您想使用傳址,請修改 array_multisort() 的宣告。如果您想啟用呼叫時傳址,您可以在您的 INI 檔案中將 allow_call_time_pass_reference 設為 true...)

來自類似這樣的程式碼

array_multisort (&$keyarr, &$arr );// 根據這些鍵排序

此訊息不容易透過變更錯誤回報層級來關閉,因為它是在剖析時產生,而不是在執行時產生。

我認為這個訊息具有誤導性,因為在 array_multisort 中,參數無論如何都會以傳址方式傳遞。

任何遇到此訊息的人都應該知道,除了刪除 & 符號之外,什麼都不需要做。
我被這個訊息欺騙了,因為我當然希望傳回 *已排序* 的陣列。而且找不到 ini 檔案或 array_multisort 的宣告。
我認為在 array_multisort 的這個描述中,應該在定義中列出傳址呼叫。

希望這對某些人有幫助
seiffs_at_centrum-dot-cz
16 年前
php_multisort($data,$keys) 必須進行兩個更正

// 排序運算式
$i=0;
$sort=''; //這裡
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++;
}
Jon L. -- intel352 [AT] gmail [DOT] com
17 年前
這是我使用 POST 值進行動態多重排序的解決方案。這沒有考慮到需要一次依多個欄位排序的情況,但可以修改以達到此目的。

<?php
/**
* @desc 您真的應該根據有效選項列表驗證發佈的排序方向。
* 選項為 SORT_ASC、SORT_DESC 等,如 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 使用值建立欄位,以便在 php 中排序
*/
$sort_arr = array();
foreach(
$array_to_sort AS $uniqid => $row){
foreach(
$row AS $key=>$value){
$sort_arr[$key][$uniqid] = $value;
}
}

print
'<b>排序前</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>排序後</b>: <br> <pre>';
print_r($array_to_sort);
print
'</pre>';

?>

這個範例會印出

排序前

陣列
(
[TestCase1] => 陣列
(
[name] => Test1
[value] => 218
)

[TestCase2] => 陣列
(
[name] => Test2
[value] => 10
)

[TestCase3] => 陣列
(
[name] => Test3
[value] => 64
)

)

排序後

陣列
(
[TestCase2] => 陣列
(
[name] => Test2
[value] => 10
)

[TestCase3] => 陣列
(
[name] => Test3
[value] => 64
)

[TestCase1] => 陣列
(
[name] => Test1
[value] => 218
)

)
KES http://kes.net.ua
18 年前
<?
// 先依第二欄排序,再依第一欄排序
$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>來源</b>";
print_r($result);

usort($result, 'KES_cmp');
print "<b>結果</b>";
print_r($result);
?>
php a-t-the-r-a-t-e chir.ag
18 年前
回覆:phu 在 kungphu,2005 年 12 月 19 日 11:36

asort($test) 不允許我指定要排序的欄位為 ASC/DESC、NUMERIC/STRING 等。

我的資料類似您指定的內容。現在我想依點數 DESC 和名稱 ASC 排序 $test。以下是我的函式,根據此頁面的建議所建立。它使用 array_multisort(因此作用就像它:保留字串索引等)。

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

?>

asort 的輸出

陣列
(
[pete] => 陣列
(
[points] => 1
[name] => Peter
)

[ab] => 陣列
(
[points] => 2
[name] => John Ab
)

[zoo] => 陣列
(
[points] => 2
[name] => John Zoo
)

[mike] => 陣列
(
[points] => 5
[name] => Mike
)

)

arrayColumnSort 的輸出

陣列
(
[mike] => 陣列
(
[points] => 5
[name] => Mike
)

[ab] => 陣列
(
[points] => 2
[name] => John Ab
)

[zoo] => 陣列
(
[points] => 2
[name] => John Zoo
)

[pete] => 陣列
(
[points] => 1
[name] => Peter
)

)
joao 在 intrasystems 點 com 點 br
19 年前
依其中一個欄位排序多維陣列的範例

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

產生

陣列
(
[0] => 陣列
(
[nome] => Pedro
[order] => 1
)

[1] => 陣列
(
[nome] => Marcelo
[order] => 3
)

[2] => 陣列
(
[nome] => Joao
[order] => 5
)

)
meddle 在 dzygn.com
20 年前
如果您想要依索引鍵名稱排序多維陣列,您無法使用 array_multisort。例如:對於名為 $archivos 的陣列,會印出如下的內容

陣列
(
[0] => 陣列
(
[index] => 0
[name] => test
)

[1] => 陣列
(
[index] => 0
[name] => watertaxi.jpg
)

[2] => 陣列
(
[index] => 0
[name] => 2_0003.JPG
)

[3] => 陣列
(
[index] => 0
[name] => 24A_0025.JPG
)

[4] => 陣列
(
[index] => 1
[name] => _CIMG3501.JPG
)

)

如果我想要依 "name" 排序,我會使用

function comparar($a, $b) {
return strnatcasecmp($a["name"], $b["name"]);
}
usort($archivos, "comparar");

此函式使用「自然排序」演算法 (strnatcasecmp) 執行不區分大小寫的字串比較,結果會是

陣列
(
[0] => 陣列
(
[index] => 0
[name] => 2_0003.JPG
)

[1] => 陣列
(
[index] => 0
[name] => 24A_0025.JPG
)

[2] => 陣列
(
[index] => 0
[name] => test
)

[3] => 陣列
(
[index] => 0
[name] => watertaxi.jpg
)

[4] => 陣列
(
[index] => 1
[name] => _CIMG3501.JPG
)

)
rnacken at gmail dot com
12 年前
當我在開發搜尋引擎時,需要依照多個參數在 PHP 中排序結果,我一度卡在多重排序會清除(數字)索引的問題上。有時候,保留這些索引是很重要的。在我的情況下,這些索引是 ID,而值則是考量先前的查詢後,物件的相關程度百分比。
例如:$searchResult = (23 => 0.3,
102 => 0.5,
11 => 0.5,
340 => 0.5,
10 => 0.9);

我想要使用 array_multisort 先依照 ID 降冪排序,然後再依照值降冪排序。也就是說,我希望優先顯示數值最高的,但如果兩個(或多個)物件的值相同,則優先顯示 ID 較高的。
例如:$searchResult = (10 => 0.9,
340 => 0.5,
102 => 0.5,
11 => 0.5,
23 => 0.3);

我認為最簡單的方法是
<?php
// 建立一個包含 $searchResult 的值和鍵的二維陣列
$array = array(
$searchResult,
array_keys($searchResult)
);
// 使用多重排序,先根據值,再根據鍵。這會清除 $searchResult 陣列中的索引
array_multisort($array[0], SORT_DESC, $array[1], SORT_DESC);
// 將排序後的鍵放回 $searchResult 陣列
$searchResult = array_combine($array[1], $array[0]);
unset(
$array); // 清除一些記憶體
?>
dwalter at seznam dot cz
5 年前
我用我的語言針對多維關聯陣列提出的解決方案,會尊重字母表中的所有字元
<?php
setlocale
(LC_COLLATE, 'cs_CZ.utf-8');
$prijmeni_zamestnancu = array_column($DBzamestnanci, 'prijmeni');
array_multisort($prijmeni_zamestnancu, SORT_ASC, SORT_LOCALE_STRING, $DBzamestnanci);
?>
To Top