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

PHP 數組排序大全:一維/二維數組、鍵值/鍵名、內置函數與自定義算法對比

     編輯:PHP 相關知識

從冒泡排序到 array_multisort:PHP 數組排序的 N 種姿勢與選型指南

數組排序是 PHP 開發高頻操作。內置提供了 sort()、usort()、array_multisort() 等十餘個函數,針對一維/二維、鍵名/鍵值、升序/降序、保持索引/重置索引等不同需求。本文系統梳理所有排序函數、自定義比較函數寫法、二維數組多鍵排序實戰、以及冒泡排序教學實現。

一、內置排序函數全景表 (核心 12 函數)

函數排序依據順序鍵名保持適用維度返回值
sort()值升序❌ 重置索引一維bool
rsort()值降序❌一維bool
asort()值升序✅ 保持關聯一維bool
arsort()值降序✅一維bool
ksort()鍵名升序✅一維bool
krsort()鍵名降序✅一維bool
usort()值 (自定義比較)自定義❌一維bool
uasort()值 (自定義)自定義✅一維bool
uksort()鍵名 (自定義)自定義✅一維bool
array_multisort()多數組/多維鍵值混合視情況多維/多數組bool
natsort()值 (自然排序)升序✅一維bool
natcasesort()值 (自然排序、大小寫不敏感)升序✅一維bool

二、一維數組排序速查

<?php
$arr = ['d'=>4, 'a'=>1, 'c'=>3, 'b'=>2];

sort($arr);    // [0=>1, 1=>2, 2=>3, 3=>4]  重置索引
asort($arr);   // ['a'=>1, 'b'=>2, 'c'=>3, 'd'=>4]  保持鍵值關聯
ksort($arr);   // ['a'=>1, 'b'=>2, 'c'=>3, 'd'=>4]  按鍵名排序

// 自然排序 (人類閱讀順序:img2.jpg < img10.jpg)
$files = ['img12.jpg', 'img1.jpg', 'img2.jpg'];
sort($files);      // ['img1.jpg', 'img12.jpg', 'img2.jpg'] ❌
natsort($files);   // ['img1.jpg', 'img2.jpg', 'img12.jpg'] ✅
?>

三、二維數組排序:array_multisort() 實戰詳解

場景:按「銷量降序、價格升序」排序商品列表。

<?php
$data = [
    ['id'=>1, 'title'=>'A', 'volume'=>67, 'price'=>20],
    ['id'=>2, 'title'=>'B', 'volume'=>86, 'price'=>15],
    ['id'=>3, 'title'=>'C', 'volume'=>85, 'price'=>30],
    ['id'=>4, 'title'=>'D', 'volume'=>98, 'price'=>25],
    ['id'=>5, 'title'=>'E', 'volume'=>86, 'price'=>10],
    ['id'=>6, 'title'=>'F', 'volume'=>67, 'price'=>35],
];

// 步驟 1:提取排序列 (列式數組)
$volumes = array_column($data, 'volume');
$prices  = array_column($data, 'price');

// 步驟 2:array_multisort 多鍵排序
// SORT_DESC 降序,SORT_ASC 升序,最後傳入原數組按引用排序
array_multisort($volumes, SORT_DESC, $prices, SORT_ASC, $data);

// 結果:volume 98→86→86→85→67→67;同 volume 86 時 price 10→15
print_r($data);
/*
Array(
    [0] => ['volume'=>98, 'price'=>25]
    [1] => ['volume'=>86, 'price'=>10]  // E
    [2] => ['volume'=>86, 'price'=>15]  // B
    [3] => ['volume'=>85, 'price'=>30]
    [4] => ['volume'=>67, 'price'=>20]  // A
    [5] => ['volume'=>67, 'price'=>35]  // F
)
*/
?>

四、通用二維數組排序封裝函數

<?php
/**
 * 二維數組多鍵排序
 * @param array &$data 待排序數組 (引用)
 * @param array $sortSpec 排序規范 [
 *     ['key'=>'volume', 'order'=>SORT_DESC],
 *     ['key'=>'price',  'order'=>SORT_ASC],
 * ]
 * @return void
 */
function arrayMultiSort(array &$data, array $sortSpec): void {
    if (empty($data) || empty($sortSpec)) return;
    $args = [];
    foreach ($sortSpec as $spec) {
        $col = array_column($data, $spec['key']);
        $args[] = $col;
        $args[] = $spec['order'] ?? SORT_ASC;
    }
    $args[] = &$data;  // 最後必須是原數組引用
    array_multisort(...$args);
}

// 使用
arrayMultiSort($products, [
    ['key' => 'sales', 'order' => SORT_DESC],
    ['key' => 'rating', 'order' => SORT_DESC],
    ['key' => 'price', 'order' => SORT_ASC],
]);
?>

五、自定義比較函數:usort() / uasort() 實戰

<?php
// 複雜邏輯:優先級 > 時間 > ID
$tasks = [
    ['id'=>1, 'priority'=>2, 'created'=>'2024-01-15'],
    ['id'=>2, 'priority'=>1, 'created'=>'2024-01-10'],
    ['id'=>3, 'priority'=>2, 'created'=>'2024-01-12'],
];

usort($tasks, function($a, $b) {
    // 1. 優先級降序
    if ($a['priority'] !== $b['priority']) return $b['priority'] <=> $a['priority'];
    // 2. 創建時間升序 (舊在前)
    $ta = strtotime($a['created']);
    $tb = strtotime($b['created']);
    if ($ta !== $tb) return $ta <=> $tb;
    // 3. ID 升序
    return $a['id'] <=> $b['id'];
});

/*
結果:
[
    ['id'=>3, 'priority'=>2, 'created'=>'2024-01-12'],  // 優先級高、時間早
    ['id'=>1, 'priority'=>2, 'created'=>'2024-01-15'],
    ['id'=>2, 'priority'=>1, 'created'=>'2024-01-10'],
]
*/
?>

六、太空船運算符 (<=>) 簡化比較函數 (PHP 7+)

<?php
// 返回 -1 (小於)、0 (相等)、1 (大於)
echo 1 <=> 2;   // -1
echo 2 <=> 1;   // 1
echo 2 <=> 2;   // 0

// 鏈式比較:完美替代嵌套 if-else
usort($arr, fn($a, $b) => 
    ($b['score'] <=> $a['score'])  // 分數降序
    ?: ($a['time'] <=> $b['time']) // 時間升序
    ?: ($a['id'] <=> $b['id'])     // ID 升序
);
?>

七、教學級:冒泡排序實現 (理解排序原理)

<?php
/**
 * 冒泡排序 (一維/二維數組指定鍵)
 * 兩兩比較相鄰元素,逆序則交換,大元素「冒泡」到末尾
 * @param array $array 待排序數組 (引用修改)
 * @param string|null $key 二維數組排序鍵
 * @return array 排序後數組
 */
function bubbleSort(array &$array, ?string $key = null): array {
    $n = count($array);
    for ($i = 0; $i < $n - 1; $i++) {
        for ($j = 0; $j < $n - 1 - $i; $j++) {
            $valJ   = $key ? $array[$j][$key]   : $array[$j];
            $valJ1  = $key ? $array[$j+1][$key] : $array[$j+1];
            if ($valJ > $valJ1) {
                [$array[$j], $array[$j+1]] = [$array[$j+1], $array[$j]];  // 交換
            }
        }
    }
    return $array;
}

// 使用
$nums = [64, 34, 25, 12, 22, 11, 90];
bubbleSort($nums);
print_r($nums);  // [11, 12, 22, 25, 34, 64, 90]

$products = [
    ['name'=>'A', 'price'=>50],
    ['name'=>'B', 'price'=>20],
    ['name'=>'C', 'price'=>80],
];
bubbleSort($products, 'price');
print_r($products);  // 按 price 升序
?>

八、選型決策表

場景推薦函數關鍵點
一維索引數組值排序、不保留鍵sort()/rsort()最快、重置索引
一維關聯數組值排序、保留鍵值關聯asort()/arsort()保持鍵值對應
一維數組按鍵名排序ksort()/krsort()鍵名字典序
一維數組複雜邏輯排序usort()/uasort()自定義比較函數、配合 <=>
二維/多維數組多鍵排序array_multisort()提取列 → 多鍵排序 → 原數組引用
自然語言排序 (文件名、版本號)natsort()/natcasesort()img2 < img10
教學/面試/極小數組冒泡/快排手寫理解原理、非生產用

性能提示

  • 內置函數均為 C 級實現,極快 (百萬級數組毫秒級)。
  • array_multisort() 需提取列佔用額外內存,超大數組 (百萬行) 考慮分塊或數據庫排序。
  • 自定義比較函數 (usort) 有 PHP 函數調用開銷,比內置排序慢 5-10 倍,盡量用 array_multisort() 替代。
  • 排序前評估:能在 SQL ORDER BY 解決的,絕不在 PHP 排序。

結語:PHP 排序函數族豐富且強大,掌握「值/鍵、升/降、保持/重置、一維/多維、內置/自定義」五個維度的組合,配合 <=> 運算符與 array_column() 提取列,能優雅解決 99% 的業務排序需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved