함수형 프로그래밍 시리즈 내용으로 계속 이어서 내용이 진행되므로 처음 부터 포스팅을 확인해주세요.
const users = [
{name:'AA', age: 35},
{name:'BB', age: 26},
{name:'CC', age: 28},
{name:'CC', age: 34},
{name:'EE', age: 23},
]
// 1
console.log(
reduce((total, u) => total + u.age, 0, users));
const add = (a, b) => a + b;
// 2
console.log(
reduce(add, L.map(u => u.age, users)));
const ages = L.map(u => u.age);
// 3
console.log(
reduce(add, ages(users)));
// 4
console.log(
reduce((total, u) => u.age >= 30 ? total : total + u.age,
0,
users)
);
// 5
console.log(
reduce(add,
L.filter(n => n < 30,
L.map(u => u.age, users)))
);
코드에서 첫 번째 console.log를 보면 total과 u.age라는 서로 다른 형태를 통해 합산을 하는 것을 알 수 있는데, reduce에서 서로 합산 할 때는 서로 형이 같아야지 더 간단하며 좋은 코드라고 할 수 있다.
다시 말해서, 하나의 보조함수에서 복잡하게 처리하는 것 보다, reduce에 집어넣기 전에 데이터를 통일 시켜서 연산하는 것이 더 좋은 코드라는 말이다.
두 번째 console.log와 같이 형이 같은 인자가 두 개 들어오는 함수의 경우에는 세 번째 console.log 처럼 심플하게 코드를 짤 수 있다.
네 번째 console.log와 같이 조건이 더 추가된 경우에는 filter를 섞어서 코드의 복잡성을 다섯 번째 console.log 처럼 줄일 수 있다.
reduce하나를 사용해서 복잡하게 사용하는 것보다, reduce와 map이나 filter를 같이 사용해서 하나의 형태를 사용하는 인자로 만들어서 사용하는 것이 다형성을 통한 함수의 재사용성 등 에서 훨씬 유리하고 이터러블 프로그래밍을 더 잘하게 되는 방법이 될 것 이다.
const obj = {
a: 1,
b: undefined,
c: 'CC',
d: 'DD'
};
// a=1&c=CC&d=DD 의 형태를 출력하게 구현하기
function query1(obj) {
let response = '';
for(const k in obj) {
const v = obj[k];
if(v === undefined) continue;
if(response !== '') response += '&';
response += `${k}=${v}`;
}
return response;
}
console.log(query1(obj));
function query2(obj) {
return Object
.entries(obj)
.reduce((query, [k, v], i) => {
if(v === undefined) return query;
return `${query}${i > 0 ? '&' : ''}${k}=${v}`;
}, '');
}
console.log(query2(obj));
const query3 = obj =>
join('&',
map(([k, v]) => `${k}=${v}`,
filter(([k, v]) => v !== undefined, Object.entries(obj))))
console.log(query3(obj));
const query4 = pipe(
Object.entries,
L.filter(([k, v]) => v !== undefined),
L.map(join('=')),
join('&')
)
console.log(query4(obj));
명령형으로 구현된 query1 부터 함수형으로 표현한 query4 까지를 통해서 우리는 단순 reduce를 활용이 아니라 map, filter를 함께 활용한 go, pipe, curry의 구현으로 훨씬 표현력이 좋은 코드를 볼 수 있다.
이번엔 위와 반대로 Query를 Object 형태로 바꾸어가며 비교해보자.
const split = curry((sep, str) => str.split(sep));
const queryToObject = pipe(
split('&'),
L.map(split('=')),
L.map(([k, v]) => ({[k] : v})),
reduce(Object.assign)
)
console.log(queryToObject('a=1&c=CC&d=DD'));
마찬가지로 reduce, map, filter를 적절히 활용하여 표현력이 좋은 코드 작성이 가능하다.