1. Tại sao phải sắp xếp mảng?

Việc thao tác với web là việc gần như hàng ngày chúng ta làm. Có rất nhiều thứ mà đã được sắp xếp trên web. Ví dụ như sắp xếp theo tên, bảng chữ cái, danh sách học sinh… Việc sắp xếp giúp người quản lý và người dùng dễ dàng tìm kiếm nội dung hơn.

Sắp xếp là 1 bài toán cơ bản và đơn giản nhất đối với bất cứ ai khi bắt đầu học lập trình. Không chỉ riêng Javascript, cho dù bạn học PHP, JAVA hay PYTHON,… bạn cũng cần phải hiểu cách sắp xếp mảng, các thuật toán sắp xếp mảng phổ biến.

Thường thì mảng sẽ theo thứ tự mà lúc đầu ta khai báo. Tuy nhiên có nhiều bài toán cần sự sắp xếp thứ tự trong mảng và ta sẽ có một số phương pháp sau:

  • Phần tử trong mảng theo thứ tự tăng dần
  • Phần tử trong mảng theo thứ tự giảm dần
  • Phần tử trong mảng theo thứ tự tùy chỉnh

2. Sắp xếp một mảng trong JavaScript

Ta sẽ sử dụng 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 hoặc giảm dần. Nó sẽ làm thay đổi mảng ban đầu của chúng ta. Cú pháp của phương thức này là:

arr.sort();
arr.sort(compareFunction);

Trong đó tham số compareFunction dùng để xác định thứ tự sắp xếp. Nếu bạn bỏ qua tham số này, mặc định Js sẽ sắp xếp mảng theo thứ tự tăng dần trong bảng mã Unicode (hay đơn giản là thứ tự tăng dần bảng chữ cái).

Ví dụ:

var thanhPhos = ["Hà Nội", "Hải Phòng", "Tuyên Quang", "Bắc Ninh", "TP HCM"];
var sorted = thanhPhos.sort();

console.log(thanhPhos);
// Kết quả: ["Bắc Ninh", "Hà Nội", "Hải Phòng", "TP HCM", "Tuyên Quang"]
console.log(sorted);
// Kết quả: ["Bắc Ninh", "Hà Nội", "Hải Phòng", "TP HCM", "Tuyên Quang"]

3. Cách sắp xếp mảng đảo ngược

Phương thức reverse() đảo ngược các phần tử trong mảng – nó là ngược lại phương thức sort() . Phương thức này đảo ngược một mảng theo cách mà phần tử mảng đầu tiên trở thành phần tử cuối cùng và phần tử mảng cuối cùng trở thành phần tử đầu tiên. Phương thức này cũng làm thay đổi giá trị của mảng ban đầu.

Ví dụ:

<p id="demo1"></p>
<p id="demo2"></p>

<script>
// Tạo và hiển thị một mảng:
const fruits = ["Banana", "Orange", "Apple", "Mango"];
document.getElementById("demo1").innerHTML = fruits;

// Đầu tiên hãy sắp xếp mảng
fruits.sort();

// Sau đó đảo ngược nó:
fruits.reverse();

document.getElementById("demo2").innerHTML = fruits;
</script>

4. Sắp xếp mảng số trong JavaScript

Vậy câu hỏi đặt ra là ta có dùng luôn được phương thức sort() để sắp xếp mảng số không. Câu trả lời là cần tuyệt đối cẩn thận khi sử dụng nhé. Bạn hãy chạy thử ví dụ sau rồi học tiếp nhé:

var score = [40, 100, 1, 6, 35, 10];
score.sort();
document.write(score);

Các bạn có thấy kết quả nó sai sai không. Phương thức sort sẽ sắp xếp các phần tử trong một mảng theo bảng chữ cái alphabet hoặc chữ số với thứ tự tăng dần hoặc giảm dần.Mặc định các phần tử sẽ được sắp xếp theo bảng chữ cái với thứ tự tăng dần. Điều này khiến phương thức sort sẽ sắp xếp các chuỗi rất chính xác, tuy nhiên khi sắp xếp các số sẽ không được chính xác và dẫn đến cái sai như ví dụ trên.

Vậy câu hỏi là làm sao để khác phục được nó. Cũng khá đơn giản nếu bạn thực hiện một hàm so sánh(compare function):

const points = [40, 100, 1, 5, 25, 10]; 
points.sort(function(a, b){return a - b});
document.write(points);

Hay sử dụng sắp xếp mảng giảm dần:

const points = [40, 100, 1, 5, 25, 10];
document.getElementById("demo2").innerHTML = points;
document.write(points);

5. Hàm so sánh trong JavaScript

Mục đích của hàm so sánh là xác định một thứ tự sắp xếp thay thế. Hàm so sánh phải trả về giá trị âm, 0 hoặc dương, tùy thuộc vào các đối số. Ví dụ:

function(a, b){return a - b}

Trước tiên, hàm sort() so sánh hai 2 trị bằng cách đưa 2 giá trị đó vào hàm so sánh. Sau đó mới thực hiện sắp xếp chúng dựa trên kết quả trả về (là giá trị âm, 0 hoặc giá trị dương).

Hay nguyên lý hoạt động của hàm so sánh trong việc sắp xếp đơn giản như sau:

  • Nếu hàm so sánh trả về giá trị nhỏ hơn 0, thì a đứng trước.
  • Nếu hàm so sánh trả về giá trị lớn hơn 0, thì b đứng trước.
  • Nếu hàm so sánh trả về 0, a và b không thay đổi đối với nhau, nhưng được sắp xếp theo tất cả các phần tử khác.

Ví dụ:

Khi so sánh 40 và 100, phương thức sort() gọi hàm so sánh compare(40,100). Hàm so sánh sẽ tính toán cho ta 40-100 và trả về kết quả -60 (giá trị âm). Hàm sort dựa vào kết quả đó nhận biết 40 nhỏ hơn 100 và tiến hành sắp xếp. Ta sẽ sử dụng đoạn mã sau để thử việc sắp xếp theo số và theo thứ tự bảng chữ cái:

<button onclick="myFunction1()">Sort Alphabetically</button>
<button onclick="myFunction2()">Sort Numerically</button>
<p id="demo"></p>

<script>
    const points = [40, 100, 1, 5, 25, 10];
    document.getElementById("demo").innerHTML = points;  

    function myFunction1() {
        points.sort();
        document.getElementById("demo").innerHTML = points;
    }
    function myFunction2() {
      points.sort(function(a, b){return a - b});
      document.getElementById("demo").innerHTML = points;
    }
</script>

6. Tìm giá trị lớn nhất, nhỏ nhất của mảng

Không có hàm đặt đặt sẵn (built-in functions) để tìm giá trị lớn nhất, nhỏ nhất của mảng. Tuy nhiên ta có thể tự linh động sau khi bạn có một mảng đã được sắp xếp, bạn có thể sử dụng chỉ số (index) để tìm được giá trị lớn nhất, nhỏ nhất của mảng đó.

Ví dụ

const points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a-b});
document.write(points);

Sắp xếp giảm dần:

const points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return b-a});
document.write(points);

Tuy nhiên sắp xếp toàn bộ một mảng là một phương pháp rất kém hiệu quả nếu bạn chỉ muốn tìm giá trị cao nhất (hoặc thấp nhất). Ta nên dùng hai cách tìm giá trị lớn nhất và nhỏ nhất trong mảng bằng việc sử dụng đối tượng Math và hàm tự thiết kế.

6.1. Sử dụng đối tượng Math

Bạn có thể dùng Math.max.apply để tìm số lớn nhất trong một mảng

<p id="demo"></p>
<script>
const points = [40, 100, 1, 5, 25, 10];
document.getElementById("demo").innerHTML = myArrayMax(points);

function myArrayMax(arr) {
  return Math.max.apply(null, arr);
}
</script>

Math.max.apply(null, [1, 2, 3]) tương đương với Math.max(1, 2, 3).

Bạn có thể sử dụng Math.min.apply để tìm số thấp nhất trong một mảng

<p id="demo"></p>

<script>
const points = [40, 100, 1, 5, 25, 10];
document.getElementById("demo").innerHTML = myArrayMin(points);

function myArrayMin(arr) {
  return Math.min.apply(null, arr);
}
</script>

Và cũng tương tự Math.min.apply(null, [1, 2, 3]) tương đương với Math.min(1, 2, 3).

6.2. Sử dụng phương thức tự thiết kế

Giải pháp nhanh nhất là ta tự làm thôi. Ở đây ta sẽ tự thiết kế ra một vòng lặp cho mảng. Lần lượt so sánh mỗi giá trị mảng thôi.

<p id="demo"></p>

<script>
const points = [40, 100, 1, 5, 25, 10];
document.getElementById("demo").innerHTML = myArrayMax(points);

function myArrayMax(arr) {
  let len = arr.length;
  let max = -Infinity;
  while (len--) {
    if (arr[len] > max) {
      max = arr[len];
    }
  }
  return max;
}
</script>

Với tìm min cũng tương tự nhé:

<p id="demo"></p>

<script>
const points = [40, 100, 1, 5, 25, 10];
document.getElementById("demo").innerHTML = myArrayMin(points);

function myArrayMin(arr) {
  let len = arr.length;
  let min = Infinity;
  while (len--) {
    if (arr[len] < min) {
      min = arr[len];
    }
  }
  return min;
}
</script>

Ở đây có thể các bạn chưa biết vòng lặp nhưng không sao các bạn chưa cần hiểu vội. Các bạn có thể biết đã, làm quen với nó rồi ta sẽ học ở những bài sau cho đỡ bỡ ngỡ nhé!