본문 바로가기

Javascript/함수형 프로그래밍

함수형 프로그래밍으로 map, filter를 만들어보자(함수를 인자로 쓰기)

반응형

함수형으로 전환하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var users = [
  {id:1,name:'ID',age:36},
  {id:2,name:'BJ',age:32},
  {id:3,name:'JM',age:32},
  {id:4,name:'PJ',age:27},
  {id:5,name:'HA',age:25},
  {id:6,name:'JE',age:26},
  {id:7,name:'JI',age:31},
  {id:8,name:'MP',age:23}
];
// 명령형 코드
// 1. 30세 이상인 users를 거른다.
var temp_users = [];
for (var i=0; users.length; i++){
  if(users[i].age >= 30){
    temp_users.push(users[i]);
  }
}
console.log(temp_users);
// 2. 30세 이상인 users의 names를 수집한다.
var names = [];
for(var i = 0; i < temp_users.length; i++){
  names.push(temp_users[i].name);
}
console.log(names);
// 3. 30세 미만인 users를 거른다.
var temp_users = [];
for (var i=0;users.length;i++){
  if(users[i].age < 30){
    temp_users.push(users[i]);
  }
}
console.log(temp_users);
// 4. 30세 미만인 users의 names를 수집한다.
var names = [];
for(var i = 0; i < temp_users.length;i++){
  names.push(temp_users[i].name);
}
console.log(names);



명령형으로 코드를 작성했을 때는 위와같이 1,2,3,4 의 문제를 해결 한다.

코드에 중복되는 부분이 많은데 그 부분을 map 과 filter를 이용하여 해결 가능하다.

filter

우선 1,3번에서 다른 부분은 조건문(if)에서 나이가 30세 이상이냐 미만이냐의 차이밖에 없다.

함수형프로그래밍에서는 그 부분을 함수로 나타내주면 된다.

1
2
3
4
5
6
7
8
9
10
function _filter(users,predi){
  var new_list = [];
  for(var i=0;i<users.length;i++){
    if(predi(users[i])){
      new_list.push(users[i]);
    }
  }
return new_list;
}
console.log(_filter(users,function(user){return user.age >= 30;}));
console.log(_filter(users,function(user){return user.age < 30;}));

 

변경하는 방법

1단계 - _filter 라는 함수를 적용한다. 인자로는 대상이 될 배열과 필터링할 함수가 들어온다.

2단계 - 기존에 중복되던 if문에서 필터링함수를 적용한다. (필터기능을 함수에 위임)

3단계 - 결과 부분을 return 으로 받는다. 끝.

 * 2단계가 인상적인데 함수형 프로그래밍에서는 추상화 단위가 함수다.


코드 설명

_filter 함수에 어떤 배열과 어떤 값을 필터링하는 함수를 넣게되면,

결과를 담을 새로운 배열 new_list를 만들고 배열의 크기만큼 반복하면서 필터함수에 값을 넘긴다.

필터함수는 조건에 맞게 true, false를 리턴하게 되고 그에 따라 조건문이 작동하여 해당 값을 새로운 배열에 푸시


*** 가장 중요한 것은 위의 _filter 함수가 단순히 users라는 배열을 위한 함수가 아니라는 것이다. ***

1
console.log(_filter([1,2,3,4],function(num){return num%2;}))


위 처럼 어떤 배열에서 숫자가 짝수인지 혹은 홀수인지 필터조건에 따라 사용이 가능하다.

이로써 _filter 함수는 재사용성이 좋은 함수형프로그래밍의 함수로 되었다.

따라서 위에 필터에서 이름을 좀 더 알맞게 지으려면 users 보다는 lists가 더 적절하다.


map


1
2
3
4
5
6
7
8
9
10
11
function _map(list, mapper){
  var new_list = [];
  for(var i = 0; i < list.length; i++){
    new_list.push(mapper(list[i]));
  }
  return new_list;
}
var over_30 = _filter(users,function(user){return user.age >= 30;});
var names = _map(over_30,function(user){
  return user.name;
})



아까 명령형 코드의 2,4번을 map으로 해결한다.

filter를 만드는 단계와 동일하게 만들면 된다.

코드 설명

기존의 _filter 함수를 이용하여 30세 이상인 사람들로만 필터링하여 그 배열을 over_30에 담았다.

_map 함수는 over_30에서 함수로 그 사람들의 이름만을 모아 배열로 리턴한다.


- _map과 _filter에도 for문이 중복되고 있는데 그것은 each로 다음 포스트에서 해결한다.

반응형