킹의 개발일지

쏙쏙 들어오는 함수형 코딩 31일차 본문

독서/책너두 챌린지

쏙쏙 들어오는 함수형 코딩 31일차

k1ng 2023. 9. 13. 18:42

31일차 <데이터를 사용해 창의적으로 만들기>

이번 파트도 저번처럼 예시 위주로 다룰 예정이다.

 

1. 포지션별로 가장 높은 사람을 골라 명단을 완성하는 코드를 만들어 보자.

 

주어진 데이터는 다음과 같다.

var evaluations = [{name: "Jane", position: "catcher", score: 25},
                  {name: "John", position: "pitcher", score: 10}, ...];
                    
// 최종 명단은 다음과 같이 만들어져야 한다.
var roster = {"pitcher: "John", "catcher": "Jane", ...};

예제에서는 이미 높은 점수순으로 정렬되어 있다고 전제를 두고있다. 하지만 정렬이 돼 있지 않은 경우까지 생각해보자.

 

일단 점수순으로 정렬하는 메서드를 만들어 보자.

function sortBy(arr, field, accending) {
  return array.slice().sort((prev, curr) => {
    if (accending ? prev[field] < curr[field] : prev[field] > curr[field]) {
      return -1;
    }
    if (accending ? prev[field] > curr[field] : prev[field] < curr[field]) {
      return 1;
    }
    return 0;
  });
}

오브젝트가 인자로 들어온다는 가정하에,  오름차순 boolean을 주어서 true면 오름차순, false면 내림차순으로 정렬 메서드를 만들 수 있다.

 

이제 정렬 메서드를 적용한 후 포지션 별로 가장 높은 사람을 골라 명단을 고르면 된다.

 

var evaluations = [{name: "Jane", position: "catcher", score: 25},
                  {name: "John", position: "pitcher", score: 10}, ...];
var isAccending = true;
var sortedEvaluations = sortBy(evaluations, "score", isAccending);
var roster = reduce(sortedEvaluations, {}, valudateByPosition);

function evaludateByPosition(roster, eval) {
  var position = eval.position;
  if (roster[position]) return roster;  // 값이 이미 있는 경우
  return objectSet(roseter, position, eval.name);  // 없는 경우 roster에 축적시키킨다.
}

위 함수는 배열을 이미 sortBy로 정렬했기에 reduce의 콜백에는 별 다른 정렬 메서드가 필요하지 않다.


2. 이미 존재하는 함수 recommendPosition을 활용하여, 직원들 이름을 대입, 추천 포지션을 얻는 메서드를 만들자.

> recommendPosition 메서드는 인자로 name을 받고 추천 포지션을 반환한다.

// 다음과 같은 배열이 있다.
var employeeNames = ["John", "Harry", "Jane", ...];

// getRecommendedPosition 콜백으로 추천 포지션 배열을 만들어주자.
var recommendations = map(employeeNames, getRecommendedPosition);

function getRecommendedPosition(name) {
  return { 
    name: name,
    position: recommendPosition(name),
  };
}

 

이름을 입력하면 추천 포지션을 반환하는 recommendPostion 메서드를 사용해서 map의 콜백으로 넘겨주면 된다.


3. 이번에도 이미 존재하는 scorePlayer 메서드를 사용해서 다음과 같은 평점 레코드를 만들어보자.

> scorePlayer는 인자로 name과 position을 받으며 두 인자에 해당하는 score을 반환한다.

{
  name: "Jane",
  position: "catcher",
  score: 25
}
var recommendations = [{name: "Jane", position: "catcher"}, {...}];

var evaluations = map(recommendations, evaluateByRecommendation);

function evaluateByRecommendation(recommendation) {
  return {
    name: recommendation.name,
    position: recommendation.position,
    score: scorePlayer(recommendation.name, recommendation.position),
  };
}

예제 2 처럼 객체를 만들어 반환해주는 콜백을 만들어서 넘겨주면된다.


4. 앞에서 만든 코드를 체이닝해서 직원 이름 명단을 통해서 정렬된 평점 목록과 낮은 점수순으로 정렬된 평점 목록을 만들어보자.

var employeeNames = ["John", "Harry", "Jane", ...];
var recommendations = map(employeeNames, getRecommendedPosition);
var evaluations = map(recommendations, evaluateByRecommendation);
// 오름차순 
var sortedEvaluations = sortBy(evaluations, "score", true);
var accendingRoster = reduce(sortedEvaluations, {}, evaludateByPosition);
// 내림차순
var sortedEvaluations = sortBy(evaluations, "score", false);
var decendingRoster = reduce(sortedEvaluations, {}, evaludateByPosition);

 


이렇게 메서드 체이닝을 사용해서 데이터를 처리하는 방버을 알아봤다. 이번 작업이 무척 도움이 됐던것이, nextjs 프레임워크를 사용해서 프로젝트를 하고있는것이 있는데, 데이터를 소스가(단기예보, 자외선, 미세먼지, 일출/몰 시간, 중기예보... 등등) 다른 여러 데이터를 내 프로젝트에서 사용할 수 있도록 공통처리를 할 필요가 있었다. 

 

이때 이런 연습들이 무척이나 도움이 됐다. 가독성과 효율성을 극대화 시킴으로써 실제로 리팩터링을 하면서 응답 시간을 단축시킬 수 있었다.

 

또한 예제들을 그냥 머리로 풀고 넘길것이 아니라 손수 작성하는것이 무척이나 도움이 됐다!