Sort array JavaScript và những phương pháp hàng đầu

Nội dung bài viết

Video học lập trình mỗi ngày

Trong bài viết này, chúng ta sẽ xem các trường hợp sử dụng phổ biến nhất cho phương thức Array sort() và cách chúng ta có thể sử dụng tối đa sức mạnh của nó.

Đây là một bài viết 41 của Series - Mẹo viết javascript mục đích giúp các bạn có thể tiết kiệm được nhiều thời gian để làm các việc khác. Ngoài ra, bạn có thể học nâng cao hơn trong Series - Con đường kiến trúc sư ở đó tập trung nhiều vào xử lý các tình huống khó hơn.

Hôm nay bài viết có lẽ mà tôi khó có thể viết tốt hơn được tác giả, bạn muốn đọc vui lòng truy cập link gốc dưới bài viết, mục đích muốn chia sẻ một số trường hợp sử dụng phổ biến nhất cho sort() phương thức Array trong JavaScript. Các phương pháp sort() sắp xếp các yếu tố của một mảng và trả về mảng được sắp xếp. Thứ tự sắp xếp mặc định tăng dần và giảm dần. Trong bài viết này, bạn sẽ xem cách chúng ta có thể sử dụng sức mạnh của nó một cách tối đa về sort().

Trước khi bắt đầu bạn cũng nên xem qua 10 tính năng phổ biến nhất của Array mà bất kỳ bạn nào cũng nên biết. Ok, đi thôi.

Sort array string JavaScript

Tăng dần (A đến Z):

Chúng ta có thể sắp xếp một mảng chuỗi đơn giản bằng cách sử dụng một phương thức mảng sort() mà không có hàm như sau:

let fruits = ['Apples', 'Watermelon', 'Bananas', 'Cherries'];
fruits.sort();    // 👈 default sort

console.log( fruits );
// ["Apples", "Bananas", "Cherries", "Watermelon"]
// A → B → C → W

Giảm dần (Z đến A): Để sắp xếp mảng chuỗi theo thứ tự giảm dần, chúng ta có thể sử dụng phương thức String localeCompare() như sau:

let fruits = ['Apples', 'Watermelon', 'Bananas', 'Cherries'];
fruits.sort((a, b) => b.localeCompare(a));

console.log( fruits );
// ["Watermelon", "Cherries", "Bananas", "Apples"]
// W → C → B → A

Sử dụng sort() có sự phân biệt chữ hoa và thường

Trước tiên, chúng ta hãy xem điều gì sẽ xảy ra khi chúng ta sắp xếp mặc định cho một mảng có chứa cả phần tử chuỗi chữ thường và chữ hoa.

let fruits = ['Apples', 'Watermelon', 'Bananas', 'cherries'];
fruits.sort(); 

console.log( fruits );
// ["Apples", "Bananas", "Watermelon", "cherries"]
// A → B → W → c
Như bạn có thể thấy đầu ra ở trên, với từ sắp xếp mặc định thì `Watermelon` bắt đầu bằng chữ hoa `W` sẽ đứng trước `cherries` bắt đầu bằng chữ thường là `c`. Điều này xảy ra vì các chuỗi được sắp xếp theo giá trị điểm mã `Unicode` của mỗi ký tự. Sử dụng `charCodeAt()` chúng ta có thể nhận được đơn vị mã `UTF-16` cho mỗi ký tự và sau đó nhận thấy rằng: 

```js
'C'.charCodeAt()   // 67
'W'.charCodeAt()   // 87
'c'.charCodeAt()   // 99

// 67 < 87 < 99
// C → W → c

Tăng dần (aA đến zZ): Đó là một sơ hở nếu bạn không biết có thể đi tìm rất mệt, để giải quyết vấn đề đó thì một giải pháp được đưa ra đó là chuyển tất cả các String về chữ thường và sau đó chúng ta tiếp tục so sánh. Bạn có thể xem ví dụ dưới đây.

let fruits = ['Apples', 'Watermelon', 'Bananas', 'cherries'];
fruits.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); 

console.log( fruits );
// ["Apples", "Bananas", "cherries", "Watermelon"]
// A → B → c → W

Hoặc một giải pháp khác...

let fruits = ['Apples', 'Watermelon', 'Bananas', 'cherries'];
fruits.sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' })); 

console.log( fruits );
// ["Apples", "Bananas", "cherries", "Watermelon"]

Sort array number JavaScript

let numbers = [4, 2, 5, 1, 3, 10];
numbers.sort();    // 👈 default sort

console.log( numbers );
//  [1, 10, 2, 3, 4, 5]

Trong ví dụ trên, chúng ta có thể thấy rằng nếu chúng ta sử dụng một sắp xếp mặc định như ví dụ trên, chúng ta sẽ nhận được đầu ra không chính xác, 10 sẽ đứng trước 2, khi mà đáng ra 10 nằm ở vị trí cuối cùng. Điều này xảy ra vì các phần tử mảng được sắp xếp bằng cách chuyển đổi chúng thành chuỗi và so sánh các chuỗi theo thứ tự đơn vị mã UTF-16. Vì vậy, trong một sắp xếp số, 2 phải đứng trước 10, nhưng vì các số được chuyển đổi thành chuỗi, nên "10" đứng trước "2" theo thứ tự Unicode.

Giải pháp cho sắp xếp tăng dần: Chúng ta có thể sắp xếp một mảng số theo thứ tự tăng dần bằng cách sử dụng một hàm so sánh đơn giản như thế này

let numbers = [4, 2, 5, 1, 3, 10];
numbers.sort((a, b) => a - b);   // 👈 compare function, simply return a - b

console.log( numbers );
// [1, 2, 3, 4, 5, 10]

Giải pháp cho sắp xếp giảm dần: Để sắp xếp một mảng số theo thứ tự giảm dần, chúng ta có thể chỉ cần hoán đổi a & b như sau:

let numbers = [4, 2, 5, 1, 3, 10];
numbers.sort((a, b) => b - a);   // 👈 interchange `a` & `b` and return b - a

console.log( numbers );
// [10, 5, 4, 3, 2, 1]

Sắp xếp một mảng chuỗi với định dạng Date

// Date string in YYYY-MM-D format
let dates = [
  '2021-08-1',
  '2021-08-4',
  '2021-08-10',
  '2021-08-2'
];
dates.sort()    // 👈 default sort

console.log( dates )
// ["2021-08-1", "2021-08-10", "2021-08-2", "2021-08-4"]

Trong ví dụ trên, chúng ta có thể thấy rằng chuỗi ngày "2021-08-10" đến trước "2021-08-2" đó không phải là kết quả chính xác. Điều này xảy ra vì lý do tương tự khi sắp xếp mảng số, nơi mà chúng tôi đã tìm thấy 10 trước đây 2 khi sử dụng sắp xếp mặc định.

Tăng dần Để sắp xếp đúng một mảng chuỗi ngày, chúng ta có thể tạo một đối tượng Date bằng cách chuyển chuỗi ngày vào new Date() bên trong hàm so sánh như sau:

let dates = [ '2021-08-1', '2021-08-4', '2021-08-10', '2021-08-2' ];
dates.sort((a, b) => new Date(a) - new Date(b))  // 👈 using `Date` constructor here

console.log( dates )
// ["2021-08-1", "2021-08-2", "2021-08-4", "2021-08-10"]

Giảm dần: Đối với thứ tự giảm dần, chúng ta có thể chỉ cần hoán đổi như sau:

let dates = [ '2021-08-1', '2021-08-4', '2021-08-10', '2021-08-2' ];
dates.sort((a, b) => new Date(b) - new Date(a))  // 👈  here

console.log( dates )
// ["2021-08-10", "2021-08-4", "2021-08-2", "2021-08-1"]

Sort object array javascript by key

Chúng ta có thể sắp xếp một mảng các đối tượng theo một giá trị thuộc tính như sau:

let inventory = [
  {name: 'Bananas', quantity: 5},
  {name: 'Apples',  quantity: 10},
  {name: 'Grapes',  quantity: 2}
];

// Sort by the "quantity" property value
inventory.sort((a, b) => a.quantity - b.quantity);  // 👈 here

console.log( inventory )
// Output
/*
[
  { "name": "Grapes",  "quantity": 2 },
  { "name": "Bananas", "quantity": 5 },
  { "name": "Apples",  "quantity": 10 }
]
*/

Đó là một sắp xếp cho thứ tự tăng dần và bạn cũng có thể làm ngược lại với chiều giảm dần.

Giảm dần: Đối với logic thứ tự giảm dần, chúng ta chỉ cần hoán đổi a & b trong hàm so sánh sắp xếp như:

let inventory = [
  {name: 'Bananas', quantity: 5},
  {name: 'Apples',  quantity: 10},
  {name: 'Grapes',  quantity: 2}
];

// Sort by the "quantity" property value
inventory.sort((a, b) => b.quantity - a.quantity);  // 👈 interchange `a` & `b` here

console.log( inventory )
// Output
/*
[
  { "name": "Apples",  "quantity": 10 },
  { "name": "Bananas", "quantity": 5 },
  { "name": "Grapes",  "quantity": 2 }
]
*/

Sort object array javascript by mutiple key

Tăng dần: Giả sử chúng ta có một mảng như thế này:

let inventory = [
  {name:"Bananas", color:"Yellow", quantity:5},
  {name:"Apples", color:"Red", quantity:4},
  {name:"Apples", color:"Green", quantity:10},
  {name:"Grapes", color:"Green", quantity:2},
  {name:"Apples", color:"Yellow", quantity:6}
];

Yêu cầu của chúng tôi là:

Đầu tiên, chúng ta cần sắp xếp các giá trị có thuộc tính name theo thứ tự tăng dần, sau đó thêm một điều kiện nữa đó là quantity tăng dần tiếp theo. Vì vậy, kết qủa sẽ như thế này:

sort array javascript

Bạn có thể làm theo nhiều cách nhưng có vẻ như cách này khá phổ biến nhất.

let inventory = [
  {name:"Bananas", color:"Yellow", quantity:5},
  {name:"Apples", color:"Red", quantity:4},
  {name:"Apples", color:"Green", quantity:10},
  {name:"Grapes", color:"Green", quantity:2},
  {name:"Apples", color:"Yellow", quantity:6}
];

// Sort by the "name" property value, then by "quantity"
inventory.sort((a, b) => {
  let compareNames = a.name.localeCompare(b.name);
  let compareQuantity = a.quantity - b.quantity;

  // First compare using names
  // If values for "name" porperty for both a & b is same,
  // then compare by "quantity" property value
  return compareNames || compareQuantity;
})

// Output is the same as shown in the above table Hoặc, bạn cũng có thể viết điều này trong một dòng như:

inventory.sort((a, b) => a.name.localeCompare(b.name) || a.quantity - b.quantity);

và kết quả không có gì thay đổi.

Tóm lại

Bài viết này thật ra nó không mới so với nhiều bạn đã có kinh nghiệm với javascript rồi. Nhưng nó là một tài liệu tốt về cách sort trong array. Và đây là một bài viết được biên dịch lại từ bài viết gốc của tác giả Palash Mondal. Bạn có thể tham khảo hơn tại bài viết gốc. Chúc các bạn đạo code giỏi hơn nữa :)

Có thể bạn đã bị missing