Rate this post

Reduce là một phương thức tích hợp sẵn giúp thực thi một hàm trên từng phần tử của mảng (từ trái sang phải), sử dụng một biến tích lũy để thu về một giá trị duy nhất. Đây là một công cụ quan trọng thường được sử dụng trong lập trình hàm.

Cú Pháp

arr.reduce(callback(accumulator, currentValue[, index[, array]]) {
  // Trả về kết quả từ việc thực thi một điều gì đó cho accumulator hoặc currentValue
}[, initialValue])

Tham số

  • callback: Hàm được thực thi cho từng phần tử của mảng, với 4 tham số là accumulator, currentValue, index, và array.
  • accumulator: Biến tích lũy, được trả về sau mỗi lần gọi hàm callback.
  • currentValue: Phần tử của mảng đang được xử lý.
  • index (Optional): Chỉ số của phần tử trong mảng đang được xử lý.
  • array (Optional): Mảng hiện tại gọi hàm reduce.
  • initialValue: Giá trị cho tham số đầu tiên (accumulator) của hàm callback trong lần gọi hàm đầu tiên. Nếu không được cung cấp, giá trị của phần tử đầu tiên trong mảng sẽ được sử dụng.

Giá Trị Trả Về

  • Chính là giá trị của accumulator sau lần gọi hàm callback cuối cùng.

Phương thức này cung cấp một cách mạnh mẽ để thực hiện các thao tác thuận tiện và tùy chỉnh trên mảng trong quá trình lập trình JavaScript.

Tại sao nên sử dụng Reduce?

Reduce là một trong những method phổ biến và linh hoạt nhất trong javascript vì nó cho phép bạn xử lý một mảng và biến nó thành bất cứ giá trị nào mà bạn muốn, vì vậy chúng tôi khuyên bạn nên học và sử dụng nó để giải quyết các vấn đề liên quan đến mảng và dữ liệu.

Ngoài việc sử dụng reduce() để tính toán và xử lý dữ liệu trong mảng, nó còn rất hữu dụng khi bạn muốn sử dụng một mảng như một bộ dữ liệu đầu vào để tính toán hoặc xử lý dữ liệu một cách tổng quát. Ví dụ như tính tổng của tất cả các giá trị trong mảng, tìm phần tử xuất hiện nhiều nhất, hoặc tìm một phần tử cụ thể trong mảng.

reduce() cũng có thể sử dụng với các kiểu dữ liệu khác nhau, như là object, string, hoặc các kiểu số nguyên, và nó cũng có thể sử dụng với các kiểu dữ liệu tùy chọn khác nhau, ví dụ như sử dụng reduce để giải quyết các vấn đề liên quan đến chuỗi, hoặc để xử lý và chuyển đổi dữ liệu trong object, hoặc tìm kiếm một giá trị đặc biệt trong object.

Ứng Dụng Phương Thức Reduce trong JavaScript

Giả sử chúng ta có một mảng biểu thị danh sách mua sắm và muốn tính tổng chi phí của tất cả các mục trong danh sách. Trong tình huống này, chúng ta có thể sử dụng phương thức reduce() của JavaScript.

Dưới đây là một ví dụ đơn giản về cách phương thức reduce() hoạt động:

const data = [5, 10, 15, 20, 25];

const totalCost = data.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
});

console.log(totalCost); // 75

Trong ví dụ trên, phương thức reduce() nhận một hàm với hai tham số là accumulatorcurrentValue.

  • Phương thức reduce() lặp qua từng giá trị trong mảng, tương tự như một vòng lặp for.
  • Trong ví dụ này, mục tiêu là thêm currentValue vào accumulator.
  • Phép tính này được lặp lại liên tục cho mỗi giá trị trong mảng, và mỗi khi giá trị currentValue chuyển sang giá trị tiếp theo trong mảng, phép tính di chuyển sang phải.
  • Khi không còn giá trị nào trong mảng, phương thức reduce() trả về tổng giá trị.

Phương thức reduce() là một công cụ mạnh mẽ giúp thực hiện các phép toán tổng hợp trên các mảng trong JavaScript một cách linh hoạt và hiệu quả.

Nguyên Lý Hoạt Động của Phương Thức reduce() trong JavaScript

Hãy xem xét đoạn mã sau để hiểu cách phương thức reduce() hoạt động trong JavaScript:

data = [2, 4, 6, 8, 10]

const reducer = (accumulator, currentValue, currentIndex, array) => accumulator + currentValue

result = data.reduce(reducer)

console.log(result)

Phương thức reduce() nhận vào một hàm với 4 tham số: accumulator, currentValue, currentIndex, và array. Dưới đây là một bảng mô tả cho biết quá trình diễn ra trên mỗi lần lặp lại:

Callback IterationAccumulatorCurrentValueCurrentIndexArrayReturn Value
First call241[2, 4, 6, 8, 10]6
Second call662[2, 4, 6, 8, 10]12
Third call1283[2, 4, 6, 8, 10]20
Fourth call20104[2, 4, 6, 8, 10]30

Giá trị được trả về bởi phương thức reduce() sẽ là giá trị của lời gọi lại (callback) cuối cùng, trong trường hợp này là 30. Trong mỗi lần lặp lại, accumulator được cập nhật bằng cách thêm currentValue, và quá trình này diễn ra cho đến khi duyệt qua tất cả các phần tử trong mảng. Phương thức reduce() mang lại khả năng thực hiện các phép tổng hợp trên mảng một cách linh hoạt và tiện lợi.

Không Truyền Giá Trị initialValue cho Phương Thức reduce()

Khi không truyền giá trị ban đầu cho hàm reduce(), reducer sẽ giả định rằng giá trị đầu tiên trong mảng làm giá trị khởi đầu. Dưới đây là một ví dụ minh họa:

data = [11, 21, 19, 18, 46]

const reducer = (accumulator, currentValue) => accumulator + currentValue

result = data.reduce(reducer)

console.log(result)

Kết quả đầu ra của đoạn mã trên sẽ là 115. Trong trường hợp này, phương thức reduce() sử dụng phần tử đầu tiên của mảng (11) làm giá trị khởi đầu và bắt đầu thực hiện phép cộng trên tất cả các phần tử, trả về một giá trị duy nhất.

Truyền một Giá Trị initialValue cho Phương Thức reduce()

Khi chúng ta truyền giá trị ban đầu làm đối số, hàm reduce() sẽ sử dụng giá trị này làm giá trị khởi đầu và bắt đầu thực hiện phép cộng. Dưới đây là một ví dụ:

data = [11, 21, 19, 18, 46]

const reducer = (accumulator, currentValue) => accumulator + currentValue

result = data.reduce(reducer, 29)

console.log(result)

Kết quả đầu ra của đoạn mã trên sẽ là 144. Trong trường hợp này, giá trị khởi đầu là 29, và phương thức reduce() bắt đầu thực hiện phép cộng trên tất cả các phần tử, bao gồm cả giá trị khởi đầu, trả về một giá trị duy nhất trong kết quả cuối cùng.

Xử Lý Lỗi TypeError khi Sử Dụng reduce() trên Mảng Rỗng và Không Cung Cấp Giá Trị initialValue

Khi sử dụng reduce() trên một mảng rỗng mà không cung cấp giá trị khởi đầu initialValue, có thể xảy ra lỗi TypeError. Dưới đây là một ví dụ minh họa:

const emptyArray = [];

const sumReducer = (accumulator, currentValue) => accumulator + currentValue;

try {
  const sum = emptyArray.reduce(sumReducer);
  console.log(sum);
} catch (error) {
  console.error(error.message);
}

Kết quả đầu ra của đoạn mã trên sẽ là:

TypeError: Reduce of empty array with no initial value

Ở đây, phương thức reduce() không thể thực hiện trên mảng rỗng mà không có giá trị khởi đầu initialValue, và một lỗi TypeError sẽ được ném ra.

Chuyển Mảng 2 Chiều thành Mảng 1 Chiều

Phương thức reduce() có thể được sử dụng để chuyển đổi mảng 2 chiều thành mảng 1 chiều. Dưới đây là một ví dụ:

const twoDimensionalArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

const flattenedArray = twoDimensionalArray.reduce((flattened, currentArray) => {
  return flattened.concat(currentArray);
}, []);

console.log(flattenedArray); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

Ở đây, chúng ta sử dụng reduce() để nối các mảng con thành một mảng duy nhất (flattenedArray).

Tìm Trung Bình bằng reduce() trong Javascript

Để tính trung bình của một mảng sử dụng phương thức reduce() trong Javascript, có thể thực hiện như sau:

const values = [11, 21, 16];

const average = values.reduce((total, value, index, array) => {
  total += value;
  if (index === array.length - 1) {
    return total / array.length;
  } else {
    return total;
  }
});

console.log(average); // 16

Ở đây, reduce() được sử dụng để tính tổng của các giá trị trong mảng (total) và sau đó trả về giá trị trung bình.

Tìm Phần Tử Trùng Lặp trong Mảng và Loại Bỏ Các Phần Tử Trùng Lặp

Để tìm số lần xuất hiện của mỗi phần tử trong một mảng và loại bỏ các phần tử trùng lặp, có thể sử dụng reduce() như sau:

const numbers = [11, 21, 16, 19, 46, 29, 46, 19, 21];

const occurrences = numbers.reduce((countMap, number) => {
  countMap[number] = (countMap[number] || 0) + 1;
  return countMap;
}, {});

console.log(occurrences); // { '11': 1, '16': 1, '19': 2, '21': 2, '29': 1, '46': 2 }

Ở đây, giá trị ban đầu của reduce() là một đối tượng rỗng ({}), và mỗi lần lặp, chúng ta kiểm tra và cập nhật số lần xuất hiện của phần tử trong đối tượng countMap.

Nhóm Các Đối Tượng Theo Một Thuộc Tính

Để nhóm các đối tượng trong mảng theo một thuộc tính cụ thể, có thể sử dụng reduce() như sau:

let students = [
  { name: 'Rick', enrollment: 60 },
  { name: 'Beth', enrollment: 40 },
  { name: 'Jerry', enrollment: 40 }
];

function groupByProperty(objectArray, property) {
  return objectArray.reduce((grouped, obj) => {
    let key = obj[property]
    if (!grouped[key]) {
      grouped[key] = []
    }
    grouped[key].push(obj)
    return grouped
  }, {})
}

let groupedStudents = groupByProperty(students, 'enrollment')
console.log(groupedStudents)

Ở đây, chúng ta sử dụng reduce() để nhóm các đối tượng theo thuộc tính “enrollment”. Kết quả trả về là một đối tượng với key là giá trị của thuộc tính và value là mảng các đối tượng có thuộc tính đó.

Lưu ý khi sử dụng Reduce.

Sử dụng reduce có thể giúp bạn viết mã ngắn gọn và dễ hiểu hơn, và trong một số trường hợp nó còn có thể hoạt động nhanh hơn so với các cách xử lý dữ liệu khác, tuy nhiên trong một số trường hợp nó có thể chậm hơn và cần phải suy nghĩ kỹ trước khi sử dụng.

Tuy nhiên, nó không phù hợp với mọi trường hợp, nếu bạn chỉ cần tìm kiếm một phần tử trong mảng thì sử dụng find hoặc filter sẽ tốt hơn, nếu bạn cần lọc một mảng thì sử dụng filter sẽ tốt hơn.

Cần phải lưu ý rằng, khi sử dụng reduce(), bạn cần đảm bảo rằng bạn có một giá trị ban đầu hợp lệ để tránh lỗi. Nếu bạn không chỉ định giá trị ban đầu, giá trị đầu tiên trong mảng sẽ được sử dụng như là giá trị ban đầu.

Cũng cần lưu ý, khi sử dụng reduce, nếu mảng rỗng hoặc chưa có giá trị ban đầu sẽ trả về undefined.

Các bài toán với mảng lớn hay dữ liệu đặc biệt khó xử lý, chúng ta có thể dùng các phương pháp tối ưu hóa bộ nhớ, ví dụ như sử dụng thuật toán lazy evaluation, hoặc tách mảng lớn thành nhiều mảng nhỏ hơn để xử lý.

Ngoài ra, reduce cũng có thể sử dụng với các mảng được tạo từ generator hoặc async iterator, nhưng có thể tốn thêm thời gian hoặc tài nguyên hơn so với các mảng thông thường.

Trong tổng quát, reduce() là một method rất linh hoạt và hữu ích trong javascript, giúp bạn xử lý và chuyển đổi dữ liệu mảng và dữ liệu một cách eficient và đơn giản. Nó cho phép bạn tạo ra các kết quả phức tạp hơn từ một mảng đã cho, nhưng cũng cần phải cẩn thận khi sử dụng nó để tránh lỗi hoặc tốn thêm tài nguyên.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Contact Me on Zalo
Call now