Frontend/JS

[JavaScript] map, filter & reduce로 결과를 만드는 함수 생성

턴태 2023. 5. 7. 23:51

reduce나 take는 하나의 결과를 만드는 함수이다.

 

이에 반해 map, filter는 배열이나 이터러블한 모나딕한 값에 원소들에게 함수들을 합성해 놓는 역할을 하고, reduce나 take는 원소들을 꺼내서 연산을 진행하기에, 최종적으로 결과를 만드는 함수다.

 

map이나 filter 같은 함수는 지연성을 가질 수 있는 함수라고 볼 수 있고, reduce 같은 함수는 연산을 시작하는 시작점을 알리는 함수라고 볼 수 있다.

 

map, filter를 반복하다가 reduce 같은 함수로 연산을 시켜서 함수를 종료하는 등으로 중간에 연산을 시작한다. 함수형으로 작업할 때, map이나 filter로 정제하다가 reduce로 값을 뽑아내도록 사고하는 것이 중요하다.

 

map, filter, reduce로 함수 생성하기

예를 들어, 객체를 넣어 URI의 querystring을 만들어 내는 함수를 map, filter, reduce를 합성하여 생성할 수 있다.

const queryStr = obj => obj;
console.log(queryStr({ limit: 10, offset: 10, type: 'notice' }));

limit, offset, type 프로퍼티의 값을 받아서 querystring으로 변환해주는 함수를 만들고자 한다.

 

키와 값을 추출해보는 함수를 먼저 작성한다.

const queryStr = obj => go(
  obj,
  Object.entries
);
console.log(queryStr({ limit: 10, offset: 10, type: 'notice' }));

// (3) [Array(2), Array(2), Array(2)]
// 0: (2) ["limit", 10]
// 1: (2) ["offset", 10]
// 2: (2) ["type", "notice"]
// length: 3
// __proto__: Array(0)

이렇게 각각 키와 값 배열을 원소로 가지는 배열을 받아낼 수 있다.

 

이제 이 값들을 하나의 문자열로 변환한다.

const queryStr = obj => go(
  obj,
  Object.entries,
  map(([k, v]) => `${k}=${v}`),
);
console.log(queryStr({ limit: 10, offset: 10, type: 'notice' }));

// (3) ["limit=10", "offset=10", "type=notice"]

마지막으로 각각을 모두 더해 하나의 querystring을 만들어준다.

const queryStr = obj => go(
  obj,
  Object.entries,
  map(([k, v] => `${k}=${v}`),
  reduce((a, b) => `${a}&${b}`)
);
console.log(queryStr({ limit: 10, offset: 10, type: 'notice' }));

// limit=10&offset=10&type=notice

인자로 받은 객체를 Object.entries를 거치고, map을 거친 다음, 마지막에 원하는 값을 reduce로 연산하여 추출했다.

 

마지막으로, obj를 인자로 받아 go 함수를 실행하기에 이를 pipe로 바꿀 수 있다.

const queryStr = pipe(
  Object.entries,
  map(([k, v]) => `${k}=${v}`),
  reduce((a, b) => `${a}&${b}`)
);

 

이번에는 함수를 어떻게 합성하여 사용할지에 대해서 배웠다. 앞서 지연 평가 함수에서 함수들을 합성하여 사용해봤는데 본격적으로 함수 합성에 대해서 배워볼 수 있어 좋았다. 약간 사고의 방향을 잡는 단계인 것 같다. 내가 원하는 대로 map과 filter를 사용하다가 특정 인사이트가 될 값을 뽑아내기 위해서는 reduce나 take 함수를 사용하는 방향을 고려하면서 코드를 작성하는 것이 함수형 프로그래밍에 있어서 좋은 접근이 될 것이다.

 

출처: 인프런 함수형 프로그래밍과 JavaScript ES6+