Một Bộ Ánh Xạ JavaScript Thông Minh Hơn: array.flatMap()
1. Smarter mapper
Hàm array.map() rất hữu ích: nó nhận một mảng và một hàm ánh xạ, sau đó trả về một mảng mới với các phần tử đã được biến đổi.
Tuy nhiên, có một phương thức khác là array.flatMap() (có từ ES2019). Phương thức này cho phép bạn không chỉ ánh xạ mà còn có thể loại bỏ hoặc thêm các phần tử mới vào mảng kết quả.
const numbers = [0, 3, 6];
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [0, 6, 12]
Trong trường hợp bạn muốn ánh xạ một-một, tức là mảng kết quả có cùng số lượng phần tử với mảng ban đầu, array.map() hoạt động rất tốt.
Nhưng nếu bạn muốn nhân đôi các số trong mảng và bỏ qua các số 0 thì sao?
Sử dụng array.map() trực tiếp không khả thi, vì phương thức này luôn tạo ra một mảng có cùng số lượng phần tử như mảng ban đầu. Tuy nhiên, bạn có thể kết hợp array.filter() và array.map():
const numbers = [0, 3, 6];
const doubled = numbers .filter(n => n !== 0) .map(n => n * 2);
console.log(doubled); // [6, 12]
Mảng doubled giờ chứa các phần tử của numbers đã được nhân đôi và không còn chứa số 0.
Kết hợp array.filter() và array.map() có thể ánh xạ và lọc mảng. Nhưng có cách nào ngắn gọn hơn không?
Có! Nhờ phương thức array.flatMap(), bạn có thể thực hiện việc ánh xạ và loại bỏ phần tử chỉ với một lần gọi phương thức.
Dưới đây là cách bạn có thể sử dụng array.flatMap() để trả về một mảng mới với các phần tử được nhân đôi, đồng thời lọc bỏ các số 0:
const numbers = [0, 3, 6];
const doubled = numbers.flatMap(number => { return number === 0 ? [] : [2 * number];
});
console.log(doubled); // [6, 12]
Bằng cách chỉ sử dụng numbers.flatMap(), bạn có thể ánh xạ một mảng sang mảng khác, đồng thời bỏ qua các phần tử nhất định trong quá trình ánh xạ.
Hãy tìm hiểu chi tiết hơn về cách array.flatMap() hoạt động.
2. array.flatMap()
Phương thức array.flatMap() nhận một hàm callback làm đối số và trả về một mảng mới đã được ánh xạ:
const mappedArray = array.flatMap((item, index, origArray) => { // ... return [value1, value2, ..., valueN];
}, thisArg);
Hàm callback được gọi cho mỗi phần tử trong mảng ban đầu với 3 đối số: phần tử hiện tại, chỉ số và mảng gốc. Mảng được trả về từ hàm callback sau đó được làm phẳng một cấp độ, và các phần tử kết quả được thêm vào mảng đã được ánh xạ.
Phương thức này cũng chấp nhận một đối số tùy chọn thứ hai, xác định giá trị this bên trong hàm callback.
Cách đơn giản nhất để sử dụng array.flatMap() là làm phẳng một mảng chứa các phần tử là mảng:
const arrays = [[2, 4], [6]];
const flatten = arrays.flatMap(item => item);
console.log(flatten); // [2, 4, 6]
Trong ví dụ trên, arrays chứa các mảng số: [[2, 4], [6]]. Gọi arrays.flatMap(item => item) sẽ làm phẳng mảng thành [2, 4, 6].
Nhưng array.flatMap() có thể làm được nhiều hơn ngoài việc làm phẳng đơn giản. Bằng cách kiểm soát số lượng phần tử mảng bạn trả về từ hàm callback, bạn có thể:
Loại bỏ phần tử khỏi mảng kết quả bằng cách trả về một mảng rỗng []
Sửa đổi phần tử đã ánh xạ bằng cách trả về một mảng với một giá trị mới [newValue]
Hoặc thêm các phần tử mới bằng cách trả về một mảng với nhiều giá trị: [newValue1, newValue2, ...].
Ví dụ, như bạn đã thấy ở phần trước, bạn có thể tạo một mảng mới bằng cách nhân đôi các phần tử, đồng thời loại bỏ các số 0:
const numbers = [0, 3, 6];
const doubled = numbers.flatMap(number => { return number === 0 ? [] : [2 * number];
});
console.log(doubled); // [6, 12]
Hãy xem chi tiết hơn về cách ví dụ trên hoạt động.
Hàm callback trả về một mảng rỗng [] nếu phần tử hiện tại là 0. Điều này có nghĩa là khi được làm phẳng, mảng rỗng [] không cung cấp giá trị nào cả.
Nếu phần tử hiện tại không phải là số 0, thì [2 * number] được trả về. Khi mảng [2 * number] được làm phẳng, chỉ có 2 * number được thêm vào mảng kết quả.
Bạn cũng có thể sử dụng array.flatMap() để tăng số lượng phần tử trong mảng đã được ánh xạ.
Ví dụ, đoạn mã sau ánh xạ một mảng số sang một mảng mới bằng cách thêm các số đã được nhân đôi và nhân ba:
const numbers = [1, 4];
const tripled = numbers.flatMap(number => { return [number, 2 * number, 3 * number];
});
console.log(tripled); // [1, 2, 3, 4, 8, 12]
3. Kết luận
Phương thức array.flatMap() là lựa chọn phù hợp nếu bạn muốn ánh xạ một mảng sang mảng mới, đồng thời kiểm soát số lượng phần tử bạn muốn thêm vào mảng đã được ánh xạ.
Hàm callback của array.flatMap(callback) được gọi với 3 đối số: phần tử hiện tại, chỉ số và mảng gốc. Mảng được trả về từ hàm callback sau đó được làm phẳng một cấp độ, và các phần tử kết quả được chèn vào mảng đã được ánh xạ.
Lưu ý rằng nếu bạn chỉ muốn ánh xạ một phần tử sang một giá trị mới duy nhất, thì hãy sử dụng array.map() tiêu chuẩn.
Thử thách: Bạn có thể triển khai một hàm filter(array, predicateFunc) trả về một mảng mới đã được lọc bằng cách sử dụng predicateFunc không? Hãy sử dụng array.flatMap() cho việc triển khai của bạn.