arr.reduce(callback[, initialValue])
매개변수
1. callback 다음의 네 가지 인수를 받는다
- totalValue: 콜백의 반환값(축적된 총 값)
- currentValue: 현재 배열 내 처리되고 있는 요소
- currentIndex(Optional): 현재 배열 내 처리되고 있는 요소의 인덱스
- array(Optional): reduce 호출에 사용되는 원 배열
2. initialValue(Optional): 콜백의 첫 번째 인수의 값에 사용되는 디폴트 값
제 포스팅 참고 예제의 일부는 아래 사이트를 번역하여 정리하였습니다.
// 예시 1
// arr의 모든 요소의 합을 구해보자!
let arr = [ 13, 63, 29, 57];
let sum = arr.reduce((total, val, idx, arr) => total + val, 0);
console.log(sum);// 162
reduce의 동작 방법은 아래와 같다. reduce는 total의 값과 val값이 서로 더해지면서 쌓이는 것을 볼 수 있다. 위 예시는 intitial value가 0임으로 total의 초기값이 0임을 확인할 수 있다.
// 예시2
// arr의 최대값과 최소값을 구해보자!
let arr = [ 13, 63, 29, 57];
let isMaxNum = arr.reduce((total, val) => total > val ? total : val);
let isMinNum = arr.reduce((total, val) => total < val ? total : val);
console.log(isMaxNum); // 63
console.log(isMinNum); // 13
최대값을 구하는 동작 과정에서 개별 값은 아래와 같다. 요소들의 앞,뒤를 비교해가면서 total값이 계속 큰 값이 들어가는 것을 볼 수 있다.
아래 예시는 삼항연산자가 아닌 함수를 이용하여 구하였다.
reduce와 map을 이용해서 배열 요소에 곱하기 2를 해보자
let data = [1, 2, 3];
// 1. reduce 사용예시
let doubled1 = data.reduce(function(acc, value) {
acc.push(value*2);
return acc;
}, []) // 초기값을 써주는 것을 잊지 말자!
// 2. map 사용예시
let doubledMap = data.map(el => el*2);
console.log(doubled1) // [2, 4, 6]
console.log(doubledMap) // [2, 4, 6]
reduce와 filter를 이용해서 홀수 요소를 갖는 배열을 만들어 보자
let data = [1,2,3,4,5,6];
// 1. reduce 사용예시
let odds = data.reduce(function(acc, item){
if(item % 2) {
acc.push(item);
}
return acc;
},[])
// 2. filter 사용예시
let oddsFilter = data.filter(el => el % 2);
console.log(odds) // [1, 3, 5]
console.log(oddsFilter) // [1, 3, 5]
만약 어떤 배열에서 짝수를 축출해서, 각 요소마다 2를 곱해줘야 한다면 어떻게 할까?
let data = [1,2,3,4,5,6];
// 1. reduce 사용예시
let reducer = data.reduce(function(acc,item) {
if(item % 2 === 0) {
acc.push(item*2);
}
return acc;
}, []);
// 2. filter과 map 사용예시
let evensFilter = data.filter(el => el % 2 === 0); // 우선 짝수를 축출한다.
let doubled = evensFilter.map(el => el * 2) // 그 후 곱하기 2를 해준다.
console.log(reducer) // [4, 8, 12]
console.log(doubled) // [4, 8, 12]
값은 같지만 reduce와 달리, filter과 map을 사용하여 2번 처리를 해야한다는 것을 알 수 있다.
let vote = ['kim', 'lee', 'song', 'song', 'kim', 'kim','lee', 'han'];
const initialValue = {}; // intialValue는 {} 임으로 결과 값은 객체이다. acc의 초기값은 {}이다
let reducer = function(acc, item) {
if(acc[item]) { // 축적된 값에 item이라는 속성이 있니?
acc[item] = acc[item] +1; // 있으면 acc.item에 +1을 해라
} else { // 없으면
acc[item] = 1; // acc.item = 1 이다
}
return acc; // 축적된 총 값을 리턴해라
};
const result = vote.reduce(reducer, initialValue);
console.log(result); // {kim: 3, lee: 2, song: 2, han: 1}
한 함수의 계산 값을 입력받아 다른 함수에 넣고, 그 값을 입력받아 또 다른 함수에 넣으려면 어떻게 해야 할까?
function increment(input) {return input + 1;}
function decrement(input) {return input -1;}
function double(input) {return input * 2;}
function halve(input){return input / 2;}
let initial_value = 1;
우선 아래와 같이 하나하나 값을 전달하는 방법이 있을 것이다.
let incremented_value = increment(initial_value);
let doubled_value = double(incremented_value);
let final_value = decrement(doubled_value);
console.log(final_value); // 3
위의 과정을 보기 가독성있고, 간결하게 정리하는 방법은 없을까?
reduce를 활용하여 위에 코드를 정리해보자.
// 여러가지 함수를 배열에 담는다.
let pipeline = [
increment,
increment,
increment,
decrement,
double,
double,
halve
];
// 배열의 요소를 함수 이름으로 하고
// reduce 함수 안에서 그 함수를 호출한다.
// 축적된 값은 함수의 전달인자로 전달한다.
let final_value = pipeline.reduce(function(acc, fn){
return fn(acc);
}, initial_value);
console.log(final_value); // 6
위와 같이 reduce의 전달인자로 함수를 받고, 축적된 값을 전달받은 함수의 인자로 반복적으로 받는 로직을 만들어 위에 복잡한 코드를 정리할 수 있겠다.👍