TIL/Javascript

TIL.92 Javascript_Reduce 함수

codermun 2021. 1. 8. 23:41
728x90
반응형

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());
728x90
반응형