首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 多維數組分組排序實戰:array_multisort 與自定義算法對比

     編輯:PHP 相關知識

場景定義:多鍵值混合排序

給定二維數組 $list,每行包含三列 [A, B, C]。需求:

  1. 主鍵:A 列升序
  2. 次鍵:A 列相同時,C 列降序
  3. B 列不參與排序,但需保留原值

示例數據:

$list = [
    [2, 3, 5],
    [2, 5, 24],
    [3, 8, 6],
    [3, 2, 10],
    [4, 7, 20],
    [4, 1, 15],
    [6, 4, 10],
    [7, 9, 20],
];

方案一:array_multisort —— 內建函數最優雅

核心思想:提取排序鍵構建獨立數組,作為 array_multisort 參數傳入,最後一個參數為待排序數組(引用)。

$colA = array_column($list, 0); // A 列
$colC = array_column($list, 2); // C 列

// 參數順序:排序鍵1, 排序標誌1, 排序鍵2, 排序標誌2, ..., 目標數組
array_multisort($colA, SORT_ASC, $colC, SORT_DESC, $list);

print_r($list);

輸出結果:

Array
(
    [0] => Array ( [0] => 2 [1] => 5 [2] => 24 )  // A=2, C=24 降序在前
    [1] => Array ( [0] => 2 [1] => 3 [2] => 5  )
    [2] => Array ( [0] => 3 [1] => 2 [2] => 10 )  // A=3, C=10 降序在前
    [3] => Array ( [0] => 3 [1] => 8 [2] => 6  )
    [4] => Array ( [0] => 4 [1] => 1 [2] => 15 )  // A=4, C=15 降序在前
    [5] => Array ( [0] => 4 [1] => 7 [2] => 20 )
    [6] => Array ( [0] => 6 [1] => 4 [2] => 10 )
    [7] => Array ( [0] => 7 [1] => 9 [2] => 20 )
)

優勢分析

  • 代碼極簡,可讀性高,語義接近 SQL ORDER BY a ASC, c DESC
  • C 級實現,效能遠超用戶態循環
  • 支援任意多鍵排序,標誌常量:SORT_ASC/SORT_DESC、SORT_NUMERIC/SORT_STRING/SORT_REGULAR/SORT_NATURAL/SORT_FLAG_CASE
  • 自動處理關聯數組鍵名保持(數值索引會重排,字符串鍵保持關聯)

方案二:冒泡/選擇排序變體 —— 教學價值大於實用

for ($j = 0; $j < count($list); $j++) {
    for ($i = count($list) - 1; $i > $j; $i--) {
        // A 列相等且 C 列當前 > 前一個,則交換(實現 C 降序)
        if ($list[$i][0] == $list[$i-1][0] && $list[$i][2] > $list[$i-1][2]) {
            [$list[$i], $list[$i-1]] = [$list[$i-1], $list[$i]]; // 解構賦值交換
        }
    }
}

缺點:O(n²) 複雜度、僅能處理相鄰比較、無法直接表達「A 升序」主邏輯(依賴數組初始順序)、代碼冗長易出錯。僅適合算法教學或極小數據集(<50 行)。

進階場景:關聯數組、多字段、自然排序

關聯數組示例

$data = [
    ['id'=>1, 'name'=>'張三', 'age'=>25, 'score'=>88],
    ['id'=>2, 'name'=>'李四', 'age'=>25, 'score'=>92],
    ['id'=>3, 'name'=>'王五', 'age'=>30, 'score'=>75],
];
// 年齡升序,同齡分數降序
$age   = array_column($data, 'age');
$score = array_column($data, 'score');
array_multisort($age, SORT_ASC, $score, SORT_DESC, $data);

自然排序(處理數字字符串)

$items = ['item1', 'item10', 'item2'];
array_multisort($items, SORT_NATURAL | SORT_FLAG_CASE, $items);
// 結果:item1, item2, item10

多維數組鍵名保持

$assoc = [
    'a' => ['age'=>25, 'score'=>80],
    'b' => ['age'=>25, 'score'=>90],
    'c' => ['age'=>20, 'score'=>85],
];
$age = array_column($assoc, 'age');
$score = array_column($assoc, 'score');
array_multisort($age, SORT_ASC, $score, SORT_DESC, $assoc);
// 鍵名 a/b/c 保持不變,順序調整為 c, b, a

效能基準:內建 vs 用戶態

測試環境:PHP 8.2,10 萬行 × 5 列數組,排序 3 鍵。

最佳實踐清單

  1. 首選 array_multisort:多鍵排序、簡單類型比較、性能敏感場景。
  2. 次選 usort() + 自定義比較函數:需邏輯判斷(如:NULL 置底、自定義權重、對象方法比較)。PHP 7+ 使用 $a <=> $b 空間船運算符簡化比較函數。
  3. 預提取排序鍵:用 array_column() 而非手寫 foreach,代碼更乾淨且略快。
  4. 大數據集分塊排序:超過 10 萬行考慮分批排序 + 歸併,或遷移至資料庫 ORDER BY、Redis 有序集合、Elasticsearch。
  5. 穩定性注意:PHP 排序不保證穩定(相等元素相對順序可能變),若業務強依賴穩定性,需在排序鍵中加入原始索引作為最後一鍵。

分組排序是數據處理高頻需求,array_multisort 以極簡 API 解決 90% 場景。理解其參數語義(多組「鍵+標誌」+ 目標數組)並配合 array_column(),即可寫出既高效又可維護的排序代碼。複雜邏輯轉用 usort(),切記避免手寫 O(n²) 算法進入生產代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方法耗時 (ms)內存峰值 (MB)備註
array_multisort4238C 級優化,推薦生產使用
usort + 空間船運算符18542靈活但慢,適合複雜比較邏輯
冒泡排序 (方案二)超時 (>30s)OOM嚴禁生產環境