Xử lý danh sách với Map, Filter & Reduce trong Javascript

Khi làm việc với Javascript, chắc hẳn bạn sẽ có những lúc trải qua tình huống cần xử lý các dữ liệu. Những lúc ấy chắc hẳn bạn sẽ sử dụng for-loops để giải quyết vấn đề này, tuy nhiên nó sẽ ngày càng trở nên rối và làm cho code của chúng ta bị phình ra. Hầu hết trong các trường hợp, sử dụng mapfilter hay reduce làm cho công việc trở nên dễ dàng hơn. Code của các bạn sẽ ‘sạch’ hơn và dễ đọc hơn. Ít nhất là như thế, khi mà bạn hiểu được cách chúng làm việc và khi nào nên sử dụng chúng.

Sau đây là một số nguyên tắc mà các bạn sử dụng để xác định nên dùng hàm nào:

  • Nếu ta có một mảng và muốn xử lý từng biến trong mảng theo cùng một các, trả về các giá trị sau khi xử lý(số lượng đúng bằng số lượng phần tử ban đầu của mảng ) thì ta sẽ sử dụng map.
  • Nếu ta đã có một mảng nhưng ta chỉ muốn lấy các phần tử theo 1 tiêu chuẩn nhất định, ta sẽ sử dụng filter.
  • Nếu ta đã có một mảng nhưng ta muốn sử dụng các giá trị trong mảng để tạo ra vài thứ khác hoàn toàn mới, ta sử dụng reduce.

Các quy tắc này nghe có vẻ mơ hồ, do đó để hiểu cách ứng dụng từng hàm, cách tốt nhất là tìm hiểu qua các ví dụ. Mình sẽ sử dụng một mảng mẫu như dưới đây:

const animals = [
    {
        "name": "cat",
        "size": "small",
        "weight": 5
    },
    {
        "name": "dog",
        "size": "small",
        "weight": 10
    },
    {
        "name": "lion",
        "size": "medium",
        "weight": 150
    },
    {
        "name": "elephant",
        "size": "big",
        "weight": 5000
    }
]

Hàm map()

Ví dụ ta cần một mảng chức tên các con vật. Nếu sử dụng for-floop:

let animal_names = [];

for (let i = 0; i < animals.length; i++) {
    animal_names.push(animals[i].name);
}

Nếu ta sử dụng hàm map():

let animal_names = animals.map((animal, index, animals) => {
    return animal.name
})

Hàm map() nhận vào 3 tham số:

  • Phần tử hiện tại của mảng.
  • Chỉ số của phần tử hiện tại trong mảng.
  • Mảng ban đầu.

1 số ưu điểm khi dùng map() thay vì for-loop:

  • Với map(), ta không cần quản lý trạng thái của vòng lặp như với for-loop.
  • Ta không cần sử dụng chỉ số để truy cập vào đúng phần tử trong mảng.
  • Ta không cần tạo mảng mới và push() từng giá trị vào. map() trả về 1 mảng mới với các giá trị đã được chỉnh sửa, do đó có thể dễ dàng gán nó cho 1 biến khác.

Có một điều bạn cần phải ghi nhớ, đó là luôn sử dụng return để trả về từng giá trị sau chỉnh sửa,  nếu không mảng trả về cuối cùng sẽ chỉ chứa các giá trị undefined

Hàm filter()

Tiếp tục với bài khác, lần này ta muốn một mảng chỉ chứa những con vật nhỏ. Nếu dùng for-loop:

let small_animals = [];

for (let i = 0; i < animals.length; i ++) {
    if (animals[i].size === "small") {
        small_animals.push(animals[i])
    }
}

Sử dụng hàm filter():

let small_animals = animals.filter((animal) => {
    return animal.size === "small"
})

Hàm filter cũng nhận vào 3 tham số như map(), tuy nhiên trong trường hợp này ta chỉ sử dụng tham số đầu tiên. Nó cũng có lợi ích như hàm map(), cũng sử dụng câu lệnh return trong thân hàm. Tuy nhiên với filter(), ta cần đảm bảo câu lệnh return trả về giá trị true hoặc false vì nó là điều điện để lọc ra giá trị phù hợp trong mảng.

Hàm reduce()

Đến với bài 3: bạn cần tính tổng trọng lượng của các con vật, đối với for-loop:

let total_weight = 0;

for (let i = 0; i < animals.length; i++) {
    total_weigth += animals[i].weight
}

Và hàm reduce():

let total_weight = animals.reduce((weight, animal, index, animals) => {
    return weight += animal.weight
}, 0)

Với hàm reduce(), các tham số truyền vào sẽ khác một chút so với 2 hàm trên:

  • Tham số đầu tiên là giá trị khởi tạo. Ta cần set giá trị khởi tạo ở cuối hàm. Trong ví dụ trên là 0. Nó có thể là bất cứ giá trị nào.
  • Tham số thứ 2 là phần tử hiện tại trong mảng.
  • Tham số thứ 3 và 4 giống với 2 hàm kể trên.

Một lần nữa, những lợi ích khi sử dụng reduce() cũng như map(), filter(), làm cho code ngắn hơn và dễ đọc hơn. Đối với lần này, hàm reduce() kế tiếp. Khi chạy đến hàm reduce() với giá trị cuối cùng trong mảng, nó sẽ trả về tổng khối lượng các con vật (giá trị weight cuối cùng) và gán vào biến total_weight.

Kết luận:

Với các ví dụ đơn giản như hướng dẫn trên, ta đã hiểu hơn về cách sử dụng hàm map, filter và redduce. Các hàm này sẽ tối ưu hơn với các dữ liệu hay mã code nhiều, phức tạp. Mình khuyên các bạn nên làm quen với chúng nếu bạn còn bỡ ngỡ. Khi đó bạn sẽ nhận ra chúng giúp cho code bạn sạch sẽ, dễ đọc và dễ quản lý hơn.

Bài viết được dịch từ:  https://hackernoon.com/understanding-map-filter-and-reduce-in-javascript-5df1c7eee464

Bài viết khác: Thay đổi size ảnh không bị méo với thuộc tính object-fit css

 

Oh My Zsh: Nâng cao trải nghiệm terminal với giao diện đẹp và các plugin tăng hiệu suất! Git cherry-pick là gì? Cách sử dụng và ví dụ Git Rebase: Gộp nhiều commit thành một để tối ưu hóa lịch sử commit 11 tính năng JavaScript mới tuyệt vời trong ES13 (ES2022) CSS diệu kỳ: Các thuộc tính CSS mà bạn có thể chưa biết Auto deploy projects với GitHub Actions – sử dụng ssh-action WordPress Gutenberg Block Server Side Render Add, Upload image trong Gutenberg Block Development Tạo Block Controls – Block Toolbar và Settings Sidebar trong WordPress Gutenberg Làm quen với các components thường dùng khi tạo Gutenberg Block

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.