Trong hướng dẫn này, mình sẽ giúp bạn học cách sử dụng phương thức sort() trong JavaScript để sắp xếp các mảng số, chuỗi và đối tượng.
Giới thiệu phương thức sort()
trong JS
Phương thức sort() trong JavaScript cho phép bạn sắp xếp các phần tử của một mảng.
Phương thức sort()
thay đổi vị trí của các phần tử trong mảng ban đầu và trả về chính mảng đó.
Theo mặc định, phương thức sort()
sắp xếp các phần tử của mảng theo thứ tự tăng dần.
> Lưu ý: Phương thức sort() chuyển các phần tử thành chuỗi và so sánh các chuỗi để xác định thứ tự.
Hãy xem xét ví dụ sau:
// Tạo một mảng ví dụ
let mangViDu = [10, 0, 1, 2, 3, 30, 20];
// Sắp xếp mảng theo thứ tự tăng dần
// với phương thức sort()
mangViDu.sort();
// In ra kết quả
console.log(mangViDu);
Kết quả ta được:
[0, 1, 10, 2, 20, 3, 30]
Không như mong đợi nhỉ :D
Trong ví dụ này, phương thức sort()
đặt 10
trước 2
bởi vì sort()
chuyển các phần tử thành chuỗi và so sánh.
Và vì chuỗi "10"
đứng trước "2"
khi thực hiện so sánh chuỗi. Thế nên chúng ta mới có kết quả như trên.
Để khắc phục điều này, bạn cần truyền một hàm so sánh cho phương thức sort()
. Phương thức sort()
sẽ căn cứ vào kết quả trả về của hàm so sánh (âm, dương) để xác định thứ tự của các phần tử.
Sau đây minh họa cú pháp của phương thức sort():
mang.sort(hamSoSanh);
Như bạn thấy, trong đó:
-
Phương thức
sort()
chấp nhận một đối số (tùy chọn) là một hàm so sánh hai phần tử của mảng.
-
Nếu bạn bỏ qua hàm so sánh, phương thức
sort()
sẽ sắp xếp các phần tử với thứ tự sắp xếp dựa trên các giá trị thứ tự Unicode của các phần tử như đã đề cập trước đó.
Còn hàm so sánh của phương thức sort() chấp nhận hai đối số và trả về một giá trị xác định thứ tự sắp xếp. Sau đây minh họa cú pháp của hàm so sánh:
function hamSoSanh(a, b) {
// ...
}
Trong đó, hàm so sánh hamSoSanh()
chấp nhận hai đối số a và b.
Phương thức sort() sẽ sắp xếp các phần tử dựa trên giá trị trả về của hàm so sánh () với các quy tắc sau:
-
Nếu
a > b
, phương thức sort()
sẽ sắp xếp a
đứng trước b
.
-
Nếu
a < b
, phương thức sort()
sắp xếp b
đứng trước a
.
-
Nếu
a = b
, phương thức sort()
coi a bằng b và giữ nguyên vị trí của chúng
Bây giờ, để sửa lỗi sắp xếp ở ví dụ trên ta sử dụng hàm so sánh như sau:
let mangViDu = [10, 0, 1, 2, 3, 30, 20];
// Sắp xếp với hàm so sánh và sort()
mangViDu.sort(function(a, b) {
if (a > b) return 1;
if (a < b) return -1;
return 0;
});
// In ra kết quả sau khi sắp xếp
console.log(mangViDu);
Kết quả:
[0, 1, 2, 3, 10, 20, 30]
Hoặc bạn có thể xác định hàm so sánh bằng cú pháp Arrow Function của ES6:
let mangViDu = [10, 0, 1, 2, 3, 30, 20];
// Sắp xếp với hàm so sánh và sort()
mangViDu.sort((a, b) => {
if (a > b) return 1;
if (a < b) return -1;
return 0;
});
// In ra kết quả sau khi sắp xếp
console.log(mangViDu);
Hoặc bạn có thể viết tắt như thế này cũng được:
let mangViDu = [10, 0, 1, 2, 3, 30, 20];
// Sắp xếp với hàm so sánh
mangViDu.sort((a, b) => a - b);
// In ra kết quả sau khi sắp xếp
console.log(mangViDu);
Hoặc viết "Clean code", dễ đọc hơn nữa bằng cách sau:
// Mảng ví dụ
let mangViDu = [10, 0, 1, 2, 3, 30, 20];
// Tạo hàm so sánh
let hamSoSanh = (a, b) => a - b;
// Sắp xếp mảng
mangViDu.sort(hamSoSanh);
// In ra mảng đã sắp xếp
console.log(mangViDu);
Bởi vì sort() sắp xếp và thay đổi chính mảng đó, thế nên chúng ta không cần tạo thêm biến để lưu trữ kết quả.
Kết quả các ví dụ trên chúng ta đều có được là:
[0, 1, 2, 3, 10, 20, 30]
Nếu bạn chưa hiểu cách sử dụng Arrow function thì tìm hiểu thêm tại bài viết các tính năng ES6 này nhé.
Sắp xếp một mảng chuỗi với sort()
Phương thức sort() cũng được sử dụng để sắp xếp mảng chuỗi. Giả sửa bạn có một mảng như sau:
// Mảng bao gồm các chuỗi
let khoaHoc = [
"java", "php", "python", "javascript", "full stack"
];
// Sắp xếp mảng chuỗi với sort()
khoaHoc.sort();
// In ra kêt quả
console.log(khoaHoc);
Kết quả ta được:
["full stack", "java", "javascript", "php", "python"]
Để sắp xếp mảng theo thứ tự giảm dần thì bạn cần chuyển logic của hàm so sánh và truyền nó vào hàm sort() như sau:
// Mảng bao gồm các chuỗi
let khoaHoc = [
"java", "php", "python", "javascript", "full stack"
];
// Sắp xếp theo thứ tự giảm dần
khoaHoc.sort((a, b) => {
if (a > b)
return -1;
if (a < b)
return 1;
return 0;
});
// In ra kêt quả
console.log(khoaHoc);
Kết quả ta được:
["python", "php", "javascript", "java", "full stack"]
Nhưng ví dụ chúng ta có mảng bao gồm cả chuỗi viết hoa như sau:
// Mảng bao gồm các chuỗi
let khoaHoc = [
"javascript", "php", "java", "PHP"
];
// Sắp xếp
khoaHoc.sort();
// In ra kết quả
console.log(khoaHoc);
Kết quả:
[PHP, java, javascript, php]
Bởi vì hàm sort() phân biệt hoa thường.
Do đó, để kết quả đúng, bạn cần chuyển các phần tử thành cùng chuỗi viết thường (hoặc cùng chuỗi viết HOA) trước.
// Mảng bao gồm các chuỗi
let khoaHoc = [
"javascript", "php", "java", "PHP"
];
// Sắp xếp mảng
khoaHoc.sort(function(a, b) {
let x = a.toLowerCase();
let y = b.toLowerCase();
return x == y ? 0 : (x > y) ? 1 : -1;
});
// In ra kết quả
console.log(khoaHoc);
Sắp xếp mảng các chuỗi không phải ký tự trong bảng mã ASCII
Ví dụ như chuỗi tiếng Việt chẳng hạn. Sắp xếp mặc định với phương thức sort() sẽ cho ra kết quả không giống như mong đợi, ví dụ:
// Mảng các chuỗi tiếng Việt
let sinhViens = ["Hương", "Hà", "Đức", "Thoa"];
// Sắp xếp
sinhViens.sort();
// In ra kết quả
console.log(sinhViens);
Kết quả:
["Hà", "Hương", "Thoa", "Đức"]
Như bạn thấy, chuỗi "Đức" lại bị xếp sau.
Để giải quyết vấn đề này, bạn sử dụng phương thức localeCompare()
của đối tượng String
để so sánh các chuỗi trong một ngôn ngữ cụ thể, như sau:
// Mảng chuỗi tiếng Việt
let sinhViens = ["Hương", "Hà", "Đức", "Thoa"];
// Sắp xếp theo ngôn ngữ cụ thể
sinhViens.sort(function(a, b) {
return a.localeCompare(b);
});
// In ra kết quả
console.log(sinhViens);
Kết quả:
["Đức", "Hà", "Hương", "Thoa"]
Kết quả như thế này mới đúng chứ.
Sắp xếp mảng số với sort()
Giả sử bạn có một mảng số có tên là diemSo
như trong ví dụ sau.
// Mảng số
let diemSo = [
3, 10, 8, 6, 7, 9
]
Để sắp xếp một mảng số theo kiểu số, bạn cần chuyển vào hàm so sánh tùy chỉnh để so sánh hai số.
Chương trình sau đây sắp xếp mảng điểm số theo thứ tự tăng dần:
// Tạo hàm so sánh
// theo thứ tự tăng dần
let hamSoSanh = (x, y) => x - y;
// Sắp sếp mảng
diemSo.sort(hamSoSanh)
//In kết quả
console.log(diemSo);
Kết quả:
[3, 6, 7, 8, 9, 10]
Bây giờ, bạn muốn sắp xếp theo thứ tự giảm dần, bạn đổi logic hàm so sánh lại như sau:
// Tạo hàm so sánh theo thứ tự giảm dần
let hamSoSanh = (x, y) => y - x;
// Sắp sếp mảng
diemSo.sort(hamSoSanh)
//In kết quả
console.log(diemSo);
Kết quả:
[10, 9, 8, 7, 6, 3]
Sắp xếp mảng các đối tượng theo thuộc tính chỉ định
Sau đây là mảng các đối tượng sinh viên bao gồm tên, tuổi và điểm môn Xác suất.
let sinhViens = [
{ ten: "Ngọc Anh", tuoi: 18, diemXacSuat: 3 },
{ ten: "Hương", tuoi: 20, diemXacSuat: 2 },
{ ten: "Hà", tuoi: 21, diemXacSuat: 1 },
{ ten: "Thoa", tuoi: 25, diemXacSuat: 4 }
];
Bây giờ, nếu muốn sắp xếp theo tuổi tăng dần, ta làm như sau:
// Sắp xếp theo tuổi tăng dần
sinhViens.sort(function(sv1, sv2) {
return sv1.tuoi - sv2.tuoi;
});
// In ra kết quả
console.table(sinhViens)
Kết quả:
Sắp xếp theo tên của từng sinh viên:
// Sắp xếp theo tên từ A - z
sinhViens.sort(function(sv1, sv2) {
let a = sv1.ten.toLowerCase();
let b = sv2.ten.toLowerCase();
return a === b ? 0 : a > b ? 1 : -1;
});
// In ra kết quả
console.table(sinhViens);
Kết quả:
Sắp xếp theo điểm Xác Suất từ cao xuống thấp:
// Sắp xếp theo điểm từ cao xuống thấp
sinhViens.sort(function(sv1, sv2) {
let a = sv1.diemXacSuat;
let b = sv2.diemXacSuat;
return b - a;
});
// In ra kết quả
console.table(sinhViens);
Kết quả:
Tối ưu hóa phương thức sort()
Trên thực tế, phương thức sort() gọi hàm so sánh nhiều lần cho mỗi phần tử trong mảng.
Xem ví dụ sau:
let sinhViens = ["Hương", "Hà", "Đức", "Thoa"];
sinhViens.sort((a, b) => {
console.log(a, b);
return a.length - b.length;
});
Kết quả trong console ta có:
Hà Hương
Đức Hà
Đức Hương
Đức Hà
Thoa Đức
Thoa Hương
Giải thích chương trình:
-
Đầu tiên, khai báo một mảng
sinhViens
bao gồm các tên sinh viên.
-
Thứ hai, sắp xếp mảng
sinhViens
theo độ dài của tên bằng cách sử dụng phương thức sort()
.
-
Bất cứ khi nào phương thức
sort()
gọi hàm so sánh, chúng ta xuất các phần tử đang so sánh ra console để xem.
Như được hiển thị trong kết quả ở trên, mỗi phần tử đã được đánh giá nhiều lần, ví dụ: Đức 3 lần, Thoa 2 lần, v.v.
Nhưng nếu số lượng phần tử của mảng ngày càng tăng, so sánh kiểu này có thể làm giảm hiệu suất, mà làm giảm hiệu suất là chứng tỏ code tệ.
> Nếu muốn học cách lập trình chuẩn, học viết code tốt hơn thì bạn nên tham HỌC JAVA hoặc HỌC LẬP TRÌNH PHP ngay tại NIIT - ICT Hà Nội để được chuyên gia doanh nghiệp nhiều kinh nghiệm hướng dẫn.
Còn để tối ưu cách sắp xếp với sort()
này, bạn không thể giảm số lần thực thi hàm so sánh đó. Tuy nhiên, bạn có thể giảm bớt công việc mà phép so sánh phải làm. Kỹ thuật này được gọi là Schwartzian Transform.
Để thực hiện điều này, bạn làm theo các bước sau:
-
Đầu tiên, trích xuất các giá cần so sánh vào một mảng tạm thời bằng phương thức map().
-
Thứ hai, sắp xếp mảng tạm thời với các phần tử đã được đánh giá (hoặc chuyển đổi).
-
Thứ ba, lưu lại đối tượng theo thứ tự phù hợp.
Đây là code:
let sinhViens = ["Hương", "Hà", "Đức", "Thoa"];
// Tạo mảng tạm thời để chứa đối tượng với vị trí
// và độ dài của phần tử
let doDaiTen = sinhViens.map(function(e, i) {
return { viTri: i, giaTri: e.length };
});
// Sắp xếp mảng chứa độ dài của tên
doDaiTen.sort(function(a, b) {
return a.giaTri - b.giaTri;
});
// Lần lượt Copy phần tử trở lại mảng sinhViens
let sinhVienDaSapXep = doDaiTen.map(function(e) {
return sinhViens[e.viTri];
});
// In ra kết quả
console.log(sinhVienDaSapXep);
Kết quả:
["Hà", "Đức", "Thoa", "Hương"]
Mặc dù chương trình này có vẻ dài hơn chương trình ban đầu. Tuy nhiên, nó cho hiệu suất tốt khi sắp xếp mảng với rất nhiều đối tượng.
Tổng kết về sort() trong JavaScript
Như vậy, trong bài hướng dẫn này, mình đã giúp bạn tìm hiểu về cách sử dụng phương thức sort()
trong JavaScript để tiến hành sắp xếp mảng, đối tượng và chuỗi một cách hiệu quả.
Hãy thực hành lại các ví dụ để nắm rõ cách sử dụng phương thức sort() hơn bạn nhé.
Tìm hiểu thêm một số phương thức quan trọng trong JavaScript:
---
HỌC VIỆN ĐÀO TẠO CNTT NIIT - ICT HÀ NỘI
Học Lập trình chất lượng cao (Since 2002). Học thực tế + Tuyển dụng ngay!
Đc: Tầng 3, 25T2, N05, Nguyễn Thị Thập, Cầu Giấy, Hà Nội
SĐT: 02435574074 - 0968051561
Email: hello@niithanoi.edu.vn
Fanpage: https://facebook.com/NIIT.ICT/
#niit #niithanoi #niiticthanoi #hoclaptrinh #khoahoclaptrinh #hoclaptrinhjava #hoclaptrinhphp #java #php #python