728x90
< 목차 >
[들어가며] 알아둬야 할 개념
0. TL;DR
1. 복잡한 반복문을 함수형 도구 체인으로 바꾸는 방법
2. 반복문을 함수형 도구로 리팩토링
3. 체이닝 디버깅을 위한 Tip
[들어가며] 알아둬야 할 개념
- 시퀀스: 컴퓨터 과학 & 프로그래밍에서 ‘특정한 순서대로 내열된 데이터’를 표현하는 자료구조 or 데이터 유형
- 데이터의 순서가 중요
- 각 요소가 그 순서에 따라 접근할 수 있는 특성을 갖고 있음
- e.g. 자바스크립트에선 배열, 문자열이 해당
- 항등 함수: 인자로 받은 값을 그대로 return 하는 함수
- 아무 일도 하지 않지만, 아무것도 하지 않아야 할 때 유용하게 사용 가능
0. TL;DR
- 체인: 여러 단계를 조합하는 것
- 원하는 결과에 가까워지도록 데이터를 한 단계씩 변환
- 기존에 있던 반복문을 함수형 도구 체인으로 리팩토링
- reduce()로 결과값 생성
- 함수형 도구를 체인으로 조합하면 복잡한 계산을 작고 명확한 단계로 표현 가능
데이터 시퀀스에 사용할 수 있는 강력한 함수형 도구에 대해 알아보자.
1. 복잡한 반복문을 함수형 도구 체인으로 바꾸는 방법
- 3개 이상 구매한 우수 고객을 거르고 (filter())
- 가장 비싼 구매를 가져오기 (map())
: 가장 비싼 구매를 찾는 코드는 reduce()로 구현 가능
// 원래 코드
function biggestPurchaseBestCustomers (customers) {
let bestCustomers = filter(customers, function (customer) {
return customer.purchases.length >= 3;
});
let biggestPurchases = map(bsetCustomers, function (customer) {
return maxKey(customer.purchases, {total: 0}, function (purchase) {
return purchase.total;
});
});
return biggestPurchases;
}
function maxKey (array, init, f) {
return reduce(array, init, function (biggestSoFar, element) {
if (f(biggestSoFar) > f(element)) {
return biggestSoFar;
} else {
return element;
}
})
}
위 코드를 토대로 체인을 명확하게 만들어 보자.
(1) 단계에 이름 붙이기
각 단계의 고차 함수를 빼내 이름을 붙일 수 있다.
// maxKey 함수만 그대로 사용. 나머지는 모두 리팩토링
function biggestPurchaseBestCustomers (customers) {
let bestCustomers = selectBestCustomers(customers); // 1단계
let biggestPurchases = getBiggestPurchases(bestCustomers); // 2단계
return biggestPurchases;
}
function selectBestCustomers (customers) {
return filter(customers, function (customer) {
return customer.purchases.length >= 3;
});
}
function getBiggestPurchases (customers) {
return map(bsetCustomers, getBiggestPurchase);
}
function getBiggestPurchase (customer) {
return maxKey(customer.purchases, {total: 0}, function (purchase) {
return purchase.total;
});
}
(2) 콜백에 이름 붙이기
function biggestPurchaseBestCustomers (customers) {
let bestCustomers = filter(customers, isGoodCustomer); // 1단계
let biggestPurchases = map(bsetCustomers, getBiggestPurchase); // 2단계
return biggestPurchases;
}
const isGoodCustomer = (customer) => customer.purchases.length >= 3;
const getBiggestPurchases = (customers) => maxKey(customer.purchases, {total: 0}, getPurchaseTotal;
const getPurchaseTotal = (purchase) => purchase.total;
⇒ 2번째 방법이 더 명확하고 가독성도 좋다.
2. 반복문을 함수형 도구로 리팩토링
- 데이터 생성
- 배열 전체를 다루기
- 작은 단계로 쪼개기
절차적 코드 vs. 함수형 코드
// 절차적인 원래 코드
// ⇒ 반복문이 중첩되고, 인덱스를 계산하며 지역변수를 바꾸는 코드
let answer = []; // 반복문 안에서 결과가 완성되는 배열
let window = 5;
for (let i = 0; i < array.length; i++) { // 외부 배열은 배열 개수만큼 반복
let sum = 0;
let count = 0;
for (let w = 0; w < window; w++) { // 내부 배열은 0~4까지 작은 구간 반복
let idx = i + w; // 새로운 인덱스 계산
if (idx < array.length) {
sum += array[idx];
count += 1; // 어떤 값 누적
}
}
answer.push(sum/count); // answer 배열에 값 추가
}
// 함수형 도구를 사용한 코드
let window = 5;
let indices = range(0, array.length); // range()로 인덱스 배열 생성
let windows = map(indices, function (i) {
return array.slice(i, i + window); // 1. slice()로 데이터 생성 (하위 배열로 만듦)
});
let answer = map(windows, averages); // 2. 한 번에 전체 배열 조작 (평균 계산, averages 함수 재사용)
// 재사용 가능한 추가 도구
// ⇒ 인덱스 배열을 만드는 코드를 빼내, 유용한 함수로 정의 (나중에 사용 가능한 함수)
function range (start, end) {
let ret = [];
for (let i = start; i < end; i++) {
ret.push(i);
}
return ret;
}
3. 체이닝 디버깅을 위한 Tip
- 구체적인 것을 유지하기
- 각 단계에서 어떤 걸 하고 있는지 알기 쉽게 작명 잘하기
- console.log()로 출력해 보기
- 각 단계 사이에 console.log() 구문을 넣어, 예상대로 동작하는지 확인
- 타입을 따라가 보기
- map()은 새로운 배열을 return. 콜백이 return 하는 타입의 값 들어있음
- reduce()는 결과값이 콜백이 return 하는 값과 같음. 초기값도 같음
728x90
'[Front-end] 개발자 공부' 카테고리의 다른 글
[개발 공부 107일차] 함수형 코딩 | 타임라인 조율하기 (12) | 2024.09.28 |
---|---|
[개발 공부 98일차] 함수형 코딩 | 타임라인 다이어그램 (0) | 2024.09.21 |
[개발 공부 89일차] 함수형 코딩 | 일급 함수 II (3) | 2024.08.28 |
[개발 공부 88일차] 함수형 코딩 | 계층형 설계 II (0) | 2024.08.26 |
[프로그래머스 Lv.2] 피보나치 수 | 개념 및 풀이 (JS) (0) | 2024.08.20 |