-
.filter().map()과 .reduce()Studying/JavaScript 2021. 10. 4. 21:42
다음과 같은 동작을 하는 함수를 생각해 보자.
정수 요소가 담긴 배열에 대하여 요소의 값이 홀수일 때만 그 값의 제곱을 새로운 배열에 담아 반환하려고 한다.
즉, [2, 5, 3, -1, 9, -5, 8]과 같은 배열을 입력 받아 [25, 9, 1, 81, 25]를 반환하는 함수를 만들려고 한다.
먼저 값이 홀수인 요소만 담아 새로운 배열을 반환하는 함수는 filter로 구현할 수 있다.
Array.prototype.filter() 메서드의 구문은 다음과 같다.
filter((element, index, array) => { ... } )
filter에 요소값, 요소 인덱스, 순회되는 배열 객체를 매개변수로 받는 콜백함수를 전달하며 호출하면
콜백함수의 반환값이 true인 경우만 요소를 유지하고, 테스트를 통과한 요소만 새로운 배열에 담아 반환해 준다.
이때 index와 array 매개변수는 선택적으로 전달할 수 있다.
값이 홀수인 요소만 통과하는 콜백함수를 전달하여 함수를 구성해 보자.
const arr = [2, 5, 3, -1, 9, -5, 8]; const odd = arr.filter(element => element % 2); console.log(odd); // [5, 3, -1, 9, -5];
filter에 전달한 콜백함수는 배열의 각 요소에 대해 element % 2의 값이 참으로 평가될 때만 요소를 유지하므로
element % 2의 값이 truthy인 1일 때, 즉 요소 값을 2로 나눈 나머지가 1인 홀수일 때만 요소를 유지하였다.
다음으로 배열의 각 요소 값의 제곱을 새로운 배열에 담아 반환하는 함수는 map()으로 구현할 수 있다.
Array.prototype.map() 메서드의 구문은 다음과 같다.
map((element, index, array) => { ... })
filter와 마찬가지로 map에 요소값, 요소 인덱스, 순회되는 배열 객체를 매개변수로 받는 콜백함수를 전달하며 호출하면
배열의 각 요소마다 콜백함수를 실행하여 콜백함수의 각 결과값을 새로운 배열에 담아 반환해 준다.
마찬가지로 index와 array 매개변수는 선택적으로 전달할 수 있다.
각 요소의 제곱을 요소로 가지는 배열을 반환하는 함수를 구성해 보자.
const arr = [5, 3, -1, 9, -5]; const square = arr.map(element => element ** 2); console.log(square); // [25, 9, 1, 81, 25];
map에 전달한 콜백함수는 배열의 각 요소에 대해 element ** 2의 값을 반환하고, map은 이 반환값들을 새로운 배열로 반환하였다.
이제 원하는 함수를 구현하기 위해 odd 함수와 square 함수를 연결하여 하나의 함수로 구성해 보자.
const arr = [2, 5, 3, -1, 9, -5, 8]; const oddSquare = arr.filter(element => element % 2).map(element => element ** 2); console.log(oddSquare); // [25, 9, 1, 81, 25]
이렇게 .filter().map()으로 원하는 함수를 구현하였다.
oddSquare 함수는 실행되는 동안 filter, map으로 배열을 두 번 순회하게 된다.
이 함수를 Array.prototype.reduce() 메서드를 이용하면 배열을 한 번 순회하며 실행되는 함수를 구성할 수 있다.
먼저 Array.prototype.reduce() 메서드의 구문은 다음과 같다.
reduce((previousValue, currentValue, currentIndex, array) => { ... }, initialValue)
reduce에 전달하는 콜백함수의 첫 번째 매개변수 previousValue에는 콜백의 반환값을 누적하는 누산기를 전달하고
currentValue에는 처리할 현재 요소, currentIndex에는 처리할 현재 요소의 인덱스,
array에는 reduce()를 호출한 배열을 전달한다.
콜백함수와 함께 reduce에 전달하는 두 번째 인수인 initialValue에는 callback의 최초 호출에서 첫 번째 인수에 제공하는 값을 전달한다. 초기값을 전달하지 않으면 배열의 첫 번째 요소를 사용하고 currentIndex가 1부터 시작하게 되는데, 빈 배열에서 초기값 없이 reduce()를 호출하면 오류가 발생하므로 항상 초기값을 전달하여 사용하는 것이 좋다.
reduce를 이용하여 oddSquare 함수를 구현해 보자.
const arr = [2, 5, 3, -1, 9, -5, 8]; const oddSquare = arr.reduce((previousArray, currentValue) => currentValue % 2 ? [...previousArray, currentValue ** 2] : previousArray, []); console.log(oddSquare); // [25, 9, 1, 81, 25]
reduce는 초기값으로 빈 배열을 전달받아
currentValue가 홀수인 경우에는 currentValue의 제곱값을 요소로 추가한 배열을,
currentValue가 짝수인 경우에는 previousArray그대로 반환하는 콜백함수를 실행하여
홀수 요소의 제곱을 새로운 배열에 담아 반환하였다.
이렇게 .filter().map()을 이용하여 구현할 수 있는 함수의 거의 대부분은 .reduce()로 동일하게 구현할 수 있으며
이때 배열 순회 횟수를 2회에서 1회로 줄일 수 있어 미세한 성능 향상 효과를 얻을 수 있다.
하지만 .filter().map()에 비해 코드가 길어지며 가독성이 현저하게 떨어지게 된다.
따라서 기본적으로는 가독성과 유지보수를 위해 .filter().map()을 사용하는 것이 좋겠으나, 매우 큰 배열을 다루거나 미세하게나마 성능 향상이 필요한 경우라면 reduce()를 사용할 수도 있다.
지금까지 filter, map, reduce 메서드와 .filter().map()을 .reduce()로 대체하는 방법까지 알아보았다.
이들은 배열을 다룰 때 가장 많이, 유용하게 이용되는 메서드라고 할 수 있다.
세 가지 메서드의 의미와 정확한 사용 방법을 충분히 익힌다면 상황에 따라 가장 적절한 메서드를 선택하여 사용할 수 있을 것이다.
반응형'Studying > JavaScript' 카테고리의 다른 글
Date 생성자함수, 프로토타입 객체의 프로퍼티 (0) 2021.10.19 표준 빌트인 객체 Date (0) 2021.10.12 Array.prototype.sort() 메서드 (0) 2021.10.03 함수 호출 방식에 따른 this 바인딩 (0) 2021.09.28 함수 이름과 기명함수, 익명함수 (2) 2021.09.13