몇일 전에 크레인인형뽑기 문제를 풀고 난 후에 다른 사람의 코드에서 reduce 메서드를 사용하는 것을 확인했고 궁금해져서 메서드에 대해 공부해봤습니다.

 

reduce

reduce 구문

arr.reduce(callback(acc, cur, curIndex, arr), initVal]);

 

reduce 인자

누적 값(acc)

현재 값(cur)

현재 인덱스 (curIndex)

원본 배열(arr)

 

그리고 initialValue라는 callback의 최초 acc에 제공하는 누적 값의 초기 값.

만약 초기 값이 없다면 자동으로 누적 값은 원본배열(arr)의 0번째 인덱스 값으로 지정됩니다.

 

간단한 예제를 보겠습니다.

// 초기 값이 없을때
[1,2,3,4,5].reduce((acc, cur, curIndex, arr) => {
	// acc는 초기값이 없으므로 [1,2,3,4,5]에서 첫번째 인덱스의 값인 1이 됩니다.
    
    // cur는 acc가 초기 값을 사용했으므로 [1,2,3,4,5]에서 그 다음 인덱스의 값인 2가 됩니다.

	// curIndex는 cur값이 2이므로 2의 인덱스인 1이 됩니다.
    
    // arr는 원본 배열인 [1,2,3,4,5]가 됩니다.
});

// 초기 값이 있을때
[1,2,3,4,5].reduce((acc, cur, curIndex, arr) => {
	// acc는 초기값이 있으므로 0이 됩니다.
    
    // cur는 [1,2,3,4,5]에서 1이 됩니다.

	// curIndex는 cur값이 1이므로 1의 인덱스인 0이 됩니다.
    
    // arr는 원본 배열인 [1,2,3,4,5]가 됩니다.
}, [0]);

이때 빈 배열에서 초기 값 없이 reduce를 호출하면 오류가 발생합니다.

 

 

초기 값이 없는 경우의 예제를 보겠습니다.

반복문의 첫번째라고 가정해보겠습니다.

var arr = [0,1,2,3,4];

arr.reduce(function(acc, cur, curIndex, arr){

  // 초기 값이 없기에 배열의 첫번째 인자값이 된다 = 0
  console.log(acc);

  // 첫번째 배열이 초기값이 되어서 cur값은 그 다음 값인 1이 된다. 
  console.log(cur);

  // cur이 1인 값을 가졌으니 1의 값의 index가 찍힌다 = arr의 1은 1번째 인덱스에 있다.
  console.log(curIndex);

  // arr은 현재 호출된 배열이므로 [0,1,2,3,4]가 찍힌다.
  console.log(arr);
});

두번째라고 가정해보겠습니다.

var arr = [0,1,2,3,4];

arr.reduce(function(acc, cur, curIndex, arr){

  // 리턴 값이 없기 때문에 undefined가 된다.
  console.log(acc);

  // 이전의 값은 1이었으니 그 다음 값이 현재 값이 되므로 2가 찍힌다. 
  console.log(cur);

  // cur이 2인 값을 가졌으니 2의 값의 index가 찍힌다 = arr의 2는 2번째 인덱스에 있다.
  console.log(curIndex);

  // arr은 현재 호출된 배열이므로 [0,1,2,3,4]가 찍힌다.
  console.log(arr);
});

이런식으로 반복이되며 배열의 길이-1 만큼 반복을 합니다.

 

 

초기 값이 있는 경우의 예제를 보겠습니다.

반복문의 첫번째라고 가정해보겠습니다.

var arr = [0,1,2,3,4];

arr.reduce(function(acc, cur, curIndex, arr){

  // 초기 값이 1이 있기 때문에 acc는 1이다.
  console.log(acc);

  // 초기값이 있었기 때문에 acc가 원본 배열의 첫번째 인덱스의 값을 가져가지 않았기 때문에 cur은 0이 된다. 
  console.log(cur);

  // cur이 0인 값을 가졌으니 0의 값의 index가 찍힌다 = arr의 0은 0번째 인덱스에 있다.
  console.log(curIndex);

  // arr은 현재 호출된 배열이므로 [0,1,2,3,4]가 찍힌다.
  console.log(arr);
}, 1);

두번째라고 가정해보겠습니다.

var arr = [0,1,2,3,4];

arr.reduce(function(acc, cur, curIndex, arr){

  // 리턴 값이 없기 때문에 undefined가 된다.
  console.log(acc);

  // 이전의 값은 0이었으니 그 다음 값이 현재 값이 되므로 1가 찍힌다. 
  console.log(cur);

  // cur이 1인 값을 가졌으니 1의 값의 index가 찍힌다 = arr의 1은 1번째 인덱스에 있다.
  console.log(curIndex);

  // arr은 현재 호출된 배열이므로 [0,1,2,3,4]가 찍힌다.
  console.log(arr);
}, 1);

 

만약 첫번째 두번째 반복에서 return이 있다면 결과가 어떻게될까?

return 값이 있는 예제를 보겠습니다.

두번째라고 가정해보겠습니다.

var arr = [0,1,2,3,4];

arr.reduce(function(acc, cur, curIndex, arr){

  // 첫번째 반복에서 acc는 1이었고 cur는 0이었다. 
  // return 1 + 0이 현재의 acc값이므로 acc는 1이다.
  console.log(acc);

  // 이전의 값은 0이었으니 그 다음 값이 현재 값이 되므로 1이 찍힌다. 
  console.log(cur);

  // cur이 1인 값을 가졌으니 1의 값의 index가 찍힌다 = arr의 1은 1번째 인덱스에 있다.
  console.log(curIndex);

  // arr은 현재 호출된 배열이므로 [0,1,2,3,4]가 찍힌다.
  console.log(arr);
  
  // acc는 1이고 cur도 1이다. 1+1로 return 2가 된다.
  return acc + cur;
}, 1);

 

이런식으로 return을 통한 인수의 총 값을 구하는 것도 가능하다.

var array = [0,1,2,3,4];

arr.reduce(function(acc, cur, curIndex, arr){
	return acc + cur;
});

 

좀 더 심화되는 코드로 배열에 중복되지 않는 숫자를 추가하는 예제를 확인해보자.

var arr = [0,1,0,2];

arr.reduce(function(acc, cur){

  // 초기값은 빈배열이다.
  // 초기값이 있기 때문에 cur은 0부터 시작한다.
  // 배열에서 cur값을 indexOf 메서드를 통해 찾는다.
  if(acc.indexOf(cur)< 0 ) 

  // acc에 cur 값을 push한다.
  acc.push(cur);

  // acc 값을 리턴한다.
  return acc;
}, []);

 

비동기 프로그래밍에서도 유용하게 쓸 수 있습니다.

const timeArr = [1000, 2000, 3000, 4000, 5000];

const factory = (time) => {
    return new Promise((resolve, reject) =. {
        setTimeout(resolve, time);
    }
};

timeArr.reduce((acc, cur) => {

  // 이전에 리턴받은 결과가 then되고나서 현재 값 전달
  return acc.then(() => factory(cur));

  // 초기값
}, Promise.resolve());

 

 


참고
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

 

 

 

+ Recent posts