PHP 陣列排序

PHP 提供多種排序函數,可以按值或鍵排序,升序或降序排列。

排序函數總覽

函數排序依據排序順序鍵的處理
sort()升序重新索引
rsort()降序重新索引
asort()升序保留鍵
arsort()降序保留鍵
ksort()升序保留鍵
krsort()降序保留鍵
usort()自訂重新索引
uasort()自訂保留鍵
uksort()自訂保留鍵

sort() - 升序排序

<?php
$arr = [3, 1, 4, 1, 5, 9, 2, 6];

sort($arr);

print_r($arr);
// [1, 1, 2, 3, 4, 5, 6, 9]
?>
所有排序函數都會直接修改原陣列,不會回傳新陣列。

rsort() - 降序排序

<?php
$arr = [3, 1, 4, 1, 5, 9, 2, 6];

rsort($arr);

print_r($arr);
// [9, 6, 5, 4, 3, 2, 1, 1]
?>

asort() - 保留鍵的升序排序

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

asort($arr);

print_r($arr);
// ['a' => 1, 'b' => 2, 'c' => 3]
?>

arsort() - 保留鍵的降序排序

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

arsort($arr);

print_r($arr);
// ['c' => 3, 'b' => 2, 'a' => 1]
?>

ksort() - 按鍵升序排序

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

ksort($arr);

print_r($arr);
// ['a' => 1, 'b' => 2, 'c' => 3]
?>

krsort() - 按鍵降序排序

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

krsort($arr);

print_r($arr);
// ['c' => 3, 'b' => 2, 'a' => 1]
?>

排序旗標

排序函數支援旗標參數來控制排序行為:

旗標說明
SORT_REGULAR預設,正常比較
SORT_NUMERIC數字比較
SORT_STRING字串比較
SORT_LOCALE_STRING根據地區設定的字串比較
SORT_NATURAL自然排序
SORT_FLAG_CASE不區分大小寫(配合 SORT_STRING 或 SORT_NATURAL)
<?php
$files = ['img12.png', 'img10.png', 'img2.png', 'img1.png'];

// 一般排序
sort($files);
print_r($files);
// ['img1.png', 'img10.png', 'img12.png', 'img2.png']

// 自然排序
sort($files, SORT_NATURAL);
print_r($files);
// ['img1.png', 'img2.png', 'img10.png', 'img12.png']
?>

usort() - 自訂排序

<?php
$arr = [3, 1, 4, 1, 5, 9, 2, 6];

// 升序
usort($arr, fn($a, $b) => $a <=> $b);
print_r($arr);  // [1, 1, 2, 3, 4, 5, 6, 9]

// 降序
usort($arr, fn($a, $b) => $b <=> $a);
print_r($arr);  // [9, 6, 5, 4, 3, 2, 1, 1]
?>

太空船運算子 (<=>)

回傳 -1、0 或 1:

<?php
echo 1 <=> 2;   // -1(左邊小)
echo 2 <=> 2;   // 0(相等)
echo 3 <=> 2;   // 1(左邊大)
?>

排序關聯陣列的陣列

<?php
$users = [
    ['name' => 'Charlie', 'age' => 35],
    ['name' => 'Alice', 'age' => 25],
    ['name' => 'Bob', 'age' => 30],
];

// 按年齡排序
usort($users, fn($a, $b) => $a['age'] <=> $b['age']);
print_r($users);
// Alice (25), Bob (30), Charlie (35)

// 按名稱排序
usort($users, fn($a, $b) => strcmp($a['name'], $b['name']));
print_r($users);
// Alice, Bob, Charlie
?>

多欄位排序

<?php
$users = [
    ['name' => 'Alice', 'age' => 25, 'score' => 80],
    ['name' => 'Bob', 'age' => 25, 'score' => 90],
    ['name' => 'Charlie', 'age' => 30, 'score' => 80],
];

// 先按年齡,再按分數(降序)
usort($users, function($a, $b) {
    // 先比較年齡
    $result = $a['age'] <=> $b['age'];
    if ($result !== 0) {
        return $result;
    }
    // 年齡相同時比較分數(降序)
    return $b['score'] <=> $a['score'];
});

print_r($users);
// Bob (25, 90), Alice (25, 80), Charlie (30, 80)
?>

array_multisort()

同時排序多個陣列或多維陣列:

<?php
$names = ['Charlie', 'Alice', 'Bob'];
$ages = [35, 25, 30];

// 按名稱排序,同時調整年齡陣列
array_multisort($names, $ages);

print_r($names);  // ['Alice', 'Bob', 'Charlie']
print_r($ages);   // [25, 30, 35]
?>

排序多維陣列

<?php
$users = [
    ['name' => 'Charlie', 'age' => 35],
    ['name' => 'Alice', 'age' => 25],
    ['name' => 'Bob', 'age' => 30],
];

// 取出要排序的欄位
$ages = array_column($users, 'age');
$names = array_column($users, 'name');

// 先按年齡升序,再按名稱升序
array_multisort($ages, SORT_ASC, $names, SORT_ASC, $users);

print_r($users);
?>

不修改原陣列的排序

<?php
$arr = [3, 1, 4, 1, 5];

// 建立副本再排序
$sorted = $arr;
sort($sorted);

print_r($arr);     // [3, 1, 4, 1, 5](不變)
print_r($sorted);  // [1, 1, 3, 4, 5]
?>

常見應用

排序物件

<?php
class Product {
    public function __construct(
        public string $name,
        public float $price
    ) {}
}

$products = [
    new Product('Apple', 1.50),
    new Product('Banana', 0.75),
    new Product('Cherry', 2.00),
];

// 按價格排序
usort($products, fn($a, $b) => $a->price <=> $b->price);

foreach ($products as $p) {
    echo "{$p->name}: \${$p->price}\n";
}
?>

保持排序順序

<?php
$users = [
    ['name' => 'Alice', 'score' => 80],
    ['name' => 'Bob', 'score' => 80],
    ['name' => 'Charlie', 'score' => 80],
];

// PHP 的排序是穩定的(相同值保持原順序)
usort($users, fn($a, $b) => $a['score'] <=> $b['score']);
// Alice, Bob, Charlie(順序保持)
?>

隨機排序

<?php
$arr = [1, 2, 3, 4, 5];

shuffle($arr);  // 隨機排序

print_r($arr);  // 隨機順序
?>

效能考量

<?php
// 對於大量資料,避免在排序函數中進行複雜計算
$users = [...]; // 大量資料

// 不好:每次比較都要計算
usort($users, fn($a, $b) => calculateScore($a) <=> calculateScore($b));

// 好:預先計算分數
$withScores = array_map(
    fn($u) => ['user' => $u, 'score' => calculateScore($u)],
    $users
);
usort($withScores, fn($a, $b) => $a['score'] <=> $b['score']);
$users = array_column($withScores, 'user');
?>

注意事項

<?php
// 排序函數會修改原陣列
$arr = [3, 1, 2];
sort($arr);
// $arr 已被修改

// 排序函數回傳布林值,不是排序後的陣列
$result = sort($arr);  // true

// 處理 null 和不同型別
$arr = [1, null, 'a', 2];
sort($arr);  // 行為可能不如預期
?>