TIL.92 Javascript_Reduce 함수
reduce()
배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.
reduce를 덧셈 함수이긴 하나 그 부분만 있는 것이아니다.
대부분의 사이트에서 reduce 사용 예시를 덧셈으로 들고 있기 때문이다.
하지만 reduce는 map과 함께 굉장히 중요하고 강력한 녀석으로 맵리듀스라는 프레임워크도 있을 정도이다.
배열.reduce((누적값, 현잿값, 인덱스, 요소) => { return 결과 }, 초깃값);
이전값이 아니라 누적값이라는 것에 주의하셔야 합니다.
누적값이기 때문에 다양하게 활용할 수 있습니다.
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
덧셈 예제
초기값 X
const oneTwoThree = [1, 2, 3];
result = oneTwoThree.reduce((acc, cur, i) => {console.log(acc, cur, i);return acc + cur;});
//
1 2 1
3 3 2
console.log(result)
// 6
초기값 O
acc(누적값)이 초깃값인 0부터 시작해서 return하는대로 누적되는 것을 볼 수 있습니다.
초깃값을 적어주지 않으면 자동으로 초깃값이 0번째 인덱스의 값이 됩니다.
const oneTwoThree = [1, 2, 3];
result = oneTwoThree.reduce((acc, cur, i) => {console.log(acc, cur, i);return acc + cur;}, 0);
//
0 1 0
1 2 1
3 3 2
console.log(result)
// 6
reduceRight
reduce와 동작은 같지만 요소 순회를 오른쪽에서부터 왼쪽으로 한다는 점이 차이
const oneTwoThree = [1, 2, 3];
result = oneTwoThree.reduceRight((acc, cur, i) => {console.log(acc, cur, i);return acc + cur;}, 0);
//
0 3 2
3 2 1
5 1 0
console.log(result)
// 6
초깃값을 활용하여 어떤 일을 할 수 있는지 알아보겠습니다.
map과 filter과 같은 함수형 메서드를 모두 reduce로 모두 구현할 수 있습니다.
map 예제를 reduce로 만들어보겠습니다.
초깃값을 배열로 만들고, 배열에 값들을 push하면 map과 같아집니다. 이를 응용하여 조건부로 push를 하면 filter와 같아집니다.
const oneTwoThree = [1, 2, 3];
result = oneTwoThree.reduce((acc, cur) => {acc.push(cur % 2 ? '홀수' : '짝수');return acc;}, []);
console.log(result)
//
[ '홀수', '짝수', '홀수' ]
홀수만 필터링하는 코드
const oneTwoThree = [1, 2, 3];
result = oneTwoThree.reduce((acc, cur) => {if (cur % 2) acc.push(cur);return acc;}, []);
console.log(result)
//
[ 1, 3 ]
이와 같이 sort, every, some, find, findIndex, includes도 다 reduce로 구현 가능합니다. reduce가 이들 모두의 아버지였던 것이다.
reduce는 비동기 프로그래밍을 할 때에도 유용합니다.
초깃값을 Promise.resolve()로 한 후에,
return된 프로미스에 then을 붙여 다음 누적값으로 넘기면 됩니다. 프로미스가 순차적으로 실행됨을 보장할 수 있습니다.
반복되는 모든 것에는 reduce를 쓸 수 있다는 것을 기억하시면 됩니다.
const promiseFactory = (time) => {
return new Promise((resolve, reject) => {
console.log(time);
setTimeout(resolve, time);
});
};
[1000, 2000, 3000, 4000].reduce((acc, cur) => {
return acc.then(() => promiseFactory(cur));
}, Promise.resolve());
// 바로 1000
// 1초 후 2000
// 2초 후 3000
// 3초 후 4000
const promiseFactory = (time) => {return new Promise((resolve, reject) => {console.log(time); setTimeout(resolve, time);});};[1000, 2000, 3000, 4000].reduce((acc, cur) => {return acc.then(() => promiseFactory(cur));}, Promise.resolve());