Menu

Sắp xếp mảng trong PHP: sort(), usort(), asort() và ksort()

sort($array) sắp xếp một danh sách ngay tại chỗ, asort và ksort sắp xếp mảng kết hợp theo giá trị hoặc theo khóa, còn usort sắp xếp theo hàm so sánh của riêng bạn. Tìm hiểu tất cả các hàm này, sắp xếp mảng nhiều chiều theo một cột, và tránh lỗi kinh điển $sorted = sort($arr).

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

sort($array) sắp xếp một mảng theo thứ tự tăng dần, ngay tại chỗ. Hàm này thay đổi biến bạn truyền vào và trả về true, nên bạn gọi nó trên một dòng riêng rồi mới dùng mảng. rsort() sắp xếp theo thứ tự giảm dần.

PHP có một hàm sắp xếp cho mỗi tổ hợp giữa "theo giá trị hay theo khóa", "tăng dần hay giảm dần" và "giữ khóa hay không":

HàmSắp xếp theoThứ tựKhóa
sortgiá trịtăng dầnđánh số lại 0, 1, 2
rsortgiá trịgiảm dầnđánh số lại
asortgiá trịtăng dầngiữ nguyên
arsortgiá trịgiảm dầngiữ nguyên
ksortkhóatăng dầngiữ nguyên
krsortkhóagiảm dầngiữ nguyên
usorthàm của bạntùy bạnđánh số lại
uasorthàm của bạntùy bạngiữ nguyên
uksorthàm của bạn trên khóatùy bạngiữ nguyên

Sắp xếp mảng kết hợp theo giá trị

sort() trên mảng kết hợp sẽ bỏ đi các khóa. Dùng asort() để sắp xếp theo giá trị mà vẫn giữ mỗi khóa đi cùng giá trị của nó, hoặc arsort() để xếp giá trị cao nhất lên đầu.

Sắp xếp mảng theo khóa với ksort

ksort() sắp xếp theo khóa, krsort() theo khóa nhưng ngược lại. Cách này tiện khi in ra các thiết lập hoặc tạo query string theo một thứ tự cố định.

Thứ tự tùy chỉnh với usort và toán tử spaceship

usort($array, $callback) cho bạn tự quyết định thứ tự. Callback nhận hai phần tử và trả về một số âm nếu phần tử thứ nhất nên đứng trước, một số dương nếu phần tử thứ hai nên đứng trước, và 0 nếu chúng bằng nhau. Toán tử spaceship <=> trả về đúng như vậy.

banana và cherry có cùng độ dài, nên callback trả về 0 cho chúng và chúng giữ nguyên thứ tự sẵn có. Sắp xếp trong PHP ổn định từ PHP 8.0: các phần tử bằng nhau giữ nguyên thứ tự trước đó.

Sắp xếp mảng nhiều chiều theo một giá trị

Để sắp xếp một danh sách các hàng theo một trường, hãy so sánh trường đó trong usort. Để sắp xếp theo hai trường, hãy so sánh các mảng: <=> so sánh chúng lần lượt từng phần tử, nên trường thứ hai chỉ dùng để phân định khi trường thứ nhất bằng nhau.

Phép so sánh thứ hai đặt $b["age"] ở vế trái và $a["age"] ở vế phải, chỉ đảo ngược thứ tự theo tuổi. array_multisort(array_column($people, 'city'), SORT_ASC, array_column($people, 'age'), SORT_DESC, $people) cho cùng thứ tự mà không cần callback: hàm này sắp xếp theo các cột đã trích ra và sắp xếp lại $people cho khớp.

Thứ tự tự nhiên và các cờ sắp xếp

Mặc định PHP so sánh số như số và chuỗi như chuỗi. Tên tệp có chứa số sẽ được xếp theo cách người ta không ngờ tới: img10 đứng trước img2, và mọi tên viết hoa đứng trước mọi tên viết thường. Các cờ thay đổi cách so sánh giá trị.

SORT_NATURAL đọc các dãy chữ số như số, SORT_FLAG_CASE bỏ qua chữ hoa và chữ thường, còn SORT_STRING buộc so sánh từng ký tự một, kể cả với chuỗi số. natsort() và natcasesort() dựa trên cùng ý tưởng nhưng giữ nguyên khóa.

Lỗi thường gặp: gán kết quả của sort

Mọi hàm sắp xếp đều trả về true và thay đổi mảng bạn truyền vào. Gán giá trị trả về sẽ làm mất mảng:

Nếu bạn cần một bản sao đã sắp xếp mà vẫn giữ mảng gốc, hãy sao chép mảng sang một biến mới trước rồi sắp xếp bản sao, giống như ví dụ asort ở trên làm với $copy.

Câu hỏi thường gặp

Vì sao sort() trả về true thay vì mảng đã sắp xếp?

Các hàm sắp xếp của PHP sắp xếp mảng ngay tại chỗ, thông qua tham chiếu, và trả về true. Hãy gọi sort($arr); trên một dòng riêng rồi dùng $arr sau đó. Viết $arr = sort($arr); sẽ thay mảng của bạn bằng true.

Làm sao sắp xếp mảng kết hợp theo giá trị mà vẫn giữ khóa?

Dùng asort($arr) để sắp xếp tăng dần hoặc arsort($arr) để sắp xếp giảm dần. sort() và rsort() cũng sắp xếp theo giá trị nhưng bỏ đi các khóa và đánh số lại từ 0.

Làm sao sắp xếp mảng nhiều chiều theo một giá trị trong PHP?

Dùng usort với toán tử spaceship trên trường đó: usort($rows, fn($a, $b) => $a['age'] <=> $b['age']);. Đổi chỗ $a và $b để sắp xếp giảm dần, và so sánh các mảng như [$a['city'], $a['age']] <=> [$b['city'], $b['age']] để sắp xếp theo hai trường.

Sắp xếp trong PHP có ổn định không?

Có, từ PHP 8.0 mọi hàm sắp xếp đều ổn định: các phần tử được so sánh là bằng nhau giữ nguyên thứ tự chúng có trước khi sắp xếp. Nhờ vậy việc sắp xếp theo một trường rồi theo trường khác mới cho kết quả như mong đợi.

Làm sao sắp xếp chuỗi có chứa số theo thứ tự tự nhiên?

Dùng natsort($arr) hoặc sort($arr, SORT_NATURAL), khi đó img2 đứng trước img10. Thêm SORT_FLAG_CASE (SORT_NATURAL | SORT_FLAG_CASE) hoặc dùng natcasesort để bỏ qua chữ hoa và chữ thường.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu