[TIL]filter와 map을 reduce로 한번에?

Violet Lee·2020년 10월 25일
0

javascript

목록 보기
20/24

만약에 어떤 수가 나열된 배열이 선언되어있고,
그 중 짝수가 아닌 홀수만을 선별하여 그 값들을 각각 *2를 한 값을 다시 배열에 넣어
리턴해주는 프로그램을 작성한다면 여러분은 어떻게 작성하겠는가?

우선 배열의 인자를 하나씩 검사하면서, 그 중 홀수인 요소만을 찾아 어떤 배열에 넣어주고,
그 배열의 인자들을 다시 하나씩 검사하면서 *2를 하여, 0번째 공간부터 다시 넣어주고,
그걸 리턴하면 되겠지- 라는 1차적인 생각이 날 것이다.

이를 간단하게 구현해본다면 이렇게 하면 될 것이다.

function filter(arr){
  let newArr1 = [];
  let newArr2 = [];
    for(let i=0;i<arr.length;i++){
    	if(arr[i] % 2 !== 0){
        	newArr1.push(arr[i]);
        }
    }

  for(let i=0;i<newArr1.length;i++){
  	newArr2.push(newArr1[i]*2);
  }
    return newArr2;
}
let a = filter([1,2,3,4,5,6,7,8,9]);
console.log(a);

배열 여러개에 이리저리 옮겨담아서 값을 거르고 변화시킬 필요없이, 한 줄안에 끝나는 방법이 있지 않을까? 해서 고차함수인 filter와 map을 사용하여, es6 문법인 화살표함수까지 사용한다면, 다음과 같이 깔끔하게 작성할 수 있다.

function filter(arr){
  let filterMaped = arr.filter(x => x%2 !== 0).map(x => x*2);
  //화살표함수를 사용하여, 고차함수의 특징인 콜백함수를 쓰지 않고, 작은 괄호와 화살표를 이용하였다. 
  //먼저 filter로 x라는 인자를 생성하여 => 다음에 조건인 '인자를 2로 나눈 나머지가 0이 아닐 때, 
  //즉 홀수일때를 거른 후, map을 사용하여 이 this의 갯수와 똑같이 리턴해주되,
  //배열의 각 요소들을 순환하면서 곱하기 2를 해주고, 
  //그걸 배열의 형태로 리턴해준다. 만약 리턴할 요소가 없다면, 빈 배열을 리턴한다.
    return filterMaped;
}
let a = filter([2,6,10]); //[].  map에 의해 리턴할 요소가 없으므로 빈 배열이 리턴된다.

위의 예제를, reduce를 사용하여 filter와 map을 한꺼번에 한 고차함수안에서 사용할수도 있다.
기본적으로 reduce 함수는

  1. accumulator(누적값)
  2. current value(현재값)
  3. current index(현재 인덱스)
  4. array(호출할 배열)

총 4가지의 인자를 가지는데,
reduce 함수의 반환 값은 누적값 accumulator에 할당되고, accumulator는 그 값이 reduce함수를 실행하는동안 계속 유지된다. 결국 최종 결과는 accumulator에 하나의 값으로 환원되는 것 이다.

reduce만을 사용하여 위의 예제를 탈바꿈한다면 다음과 같이 작성할수도 있을것이다.

function filter(arr){
  
  let arr2 = arr.reduce((acc,cur) => { //콜백함수 사용없이 작은괄호와 => 기호로,
    //누적값 acc와 현재 가리키는 배열의 요소 cur을 배열 arr에서 인자로 받아온다.
    if(cur%2 !== 0) { //만약 현재 요소를 2로 나눈 나머지가 0이 아니라면,
        acc.push(cur*2) //미리 초깃값으로 선언해둔 빈 배열 acc에 cur값을, 곱하기 2를 하여 push한다.
    }
    return acc; //최종적으로 탈바꿈한 요소들이 담긴, 하나의 배열이 되어 리턴된다.
  },[]);    
    return arr2; //이제 탈바꿈한 요소들이 담긴, 배열 arr2를 리턴한다.   
}
let a = filter([2,6,10]); //reduce함수안의 조건에 해당하지 않는 요소들만 있으므로,
//if문을 건너뛰어서 acc에 push하지 않게되어, 결국 아무것도 담기지못한 빈 배열이 리턴된다.
console.log(a); //=> [].

이는 여러 배열을 선언하여 일일이 값을 바꿔줄 필요없이,
어떤 데이터가 있고, 그 데이터의 기본 틀을 변환하지 않는 선에서,
그 데이터안의 값 들을 여러개의 조건으로 걸러서 빠르게 리턴해야 할때 사용하기 용이할것이다.

예를 들면, 여러 학생의 데이터가 있는데, 그 학생들의 모든 과목의 성적들을 하나하나 순환하면서
그 성적의 값들을 더해주어 평균값으로 환원하여, 오직 성적데이터만을 변경한 기존의 데이터를 원할 때 등이 있을것이다.

후기
이번에 과제하면서 배운 es6 문법을 잘 사용하니 보기에 깔끔해졌다.
기존에 했던 과제들을 한번 => 를 사용해봐야 할 것같다.

profile
예비개발자

0개의 댓글