킹의 개발일지

쏙쏙 들어오는 함수형 코딩 (26 ~ 27일차) 본문

독서/책너두 챌린지

쏙쏙 들어오는 함수형 코딩 (26 ~ 27일차)

k1ng 2023. 9. 7. 22:22

26일차

<함수형 반복>  'map()과 filter()'

이전에는 로우 레벨의 for문을 사용해서 forEach를 만들어 봤었다. forEach, map, filter, reduce는 프로그래밍을 하면서 상당히 많이 써봤던 함수들이다. 이번 파트에서는 map함수와 filter함수를 만들어 볼 것이다.

 

먼저 아램 메서드와 행동이 비슷한 함수들이 있다고 생각해보자. 행동은 배열을 돌면서 특정 함수를 적용하고, 함수가 적용된 배열을 반환한다.(우리가 흔히 사용하는 map함수)

function emailsForCustomers(customers, goods, bests) {
  var emails = [];
  forEach(customers, (customer) => {
    var email = emailForCustomer, goods, bests);
    emails.push(email);
  }
  return emails;
}

 

이 함수를 일반화 할 수 있는데, 함수 본문을 콜백으로 바꾸기 리팩터링을 적용하면 된다.

 

여기서 map함수가 등장한다.

function emailForCustomers(customers, goods, bests) {
  return map(customers, (customer) => emailForCunstomer(customer, goods, bests));
}
function map(arr, f) {
  var newArray = [];
  forEach(array, (elem) => newArray.push(f(elem)));
  return newArray;
}

그러나 map 함수는 해당 array에 null이 있든 없든 상관하지 않는다. 이때 null을 없애고 싶다면 filter 함수를 사용하면 된다.

 

예시를 들어보자.

 

고객들중에 구해 횟수가 3번을 넘어가는 회원을 고르는 함수를 생각해보자.

function selectBestCunstomers(customers) {
  var newArray = [];
  forEach(customers, (customer) => {
    if (customer.parchases.length >= 3)
      newArray.push(customer);
    })
  return newArray;
}

 

이를 map함수가 그랬듯 함수 본문을 콜백으로 빼주는 리팩터링을 적용시켜보자.

 

function selectBestCustomer(customer) {
  return filter(customers, (customer)) => {
    if (customer.length >= 3) 
      return customer;
  });
}
function filter(arr, f) {
  var newArray = [];
  forEach(array, (elem) => {
    if (f(elem)) newArray.push(customer)
  });
  return newArray;
}

언어 차원에서 제공하는 함수기에 블랙박스처럼 예시처럼 내부에서는 어떻게 돌아갈지는 진지하게 생각해본적이 없었다. 물론 언어차원에서 제공하는 함수는 예외 처리 같은것들이 이 책에서 만들어본 함수보다  더 잘돼 있을 것이 분명하지만 이렇게 직접 구현해보기는 처음이었다.

저자가 왜 이럴 필요가 있으며 어떤 사항들이 필요한지 설명을 잘 해줘서 변환 과정은 막상 어렵게 느껴지진 않았다. 

오늘 파트는 실습 예시들이 많았기에 리뷰가 좀 적다. 내일 있을 reduce도 기대가 된다.


27일차

<reduce>

이번 파트도 forEach, filter, map과 함께 자바스크립트를 써봤으면 한 번쯤 다뤄봤을 reduce 메서드를 구현해봤다. 

recude 메서드는 배열을 순회하면서 값을 누적해 가는 함수이다.

 

어제와 마찬가지로 예시를 보자.

function countAllPurchases(customers) {
  var total = 0;
  forEach(customers, (customer) => total = total + customer.purchases.length);
  return total;
}

이 함수에 함수 본문을 콜백으로 바꾸기 리팩터링을 적용해보자.

 

function countAllPurchases(customers) {
  return reduce(customers, 0, (total, customer) => total + customer.purchases.length);
}

 

function reduce(array, init, f) {
  var accum = init;
  forEach(array, (elem) => accum = f(elem))
  return accum;
}


이번 파트를 읽으면서 느꼈던 점은 어제와 동일하다. 오히려 어제 읽은 파트가 이번 reduce가 어떻게 구현될 지 힌트를 제공해준 셈이었다.

어제 처럼 실습 예시가 많았기에 리뷰가 적지만 recude 메서들를 사용해서 map, filter 메서드를 구현해보도록 하겠다.

1. map

function map(arr, f) {
  return reduce(arr, [], (result, elem) => result.push(f(elem)));
}



2. filter

function filter(arr, f) {
  return reduce(arr, [], (result, elem) => {
    if (f(elem)) result.push(elem);
      return result;
    });
}