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); // 行為可能不如預期
?>