📚 이론정리/JS & TS
✏️ Reduce 함수
서카츄
2024. 1. 3. 19:16
Reduce는 배열의 모든 요소를 순회하면서 하나의 결과값을 만들어내는 배열 메서드이다
"배열" 메서드 인게 중요!
기본 문법
// reduce의 기본 문법
array.reduce((누적값, 현재값) => {
// 계산 로직
return 새로운누적값;
}, 초기값);
예시)
// 1. 숫자 배열의 합계 구하기
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, cur) => {
console.log(`누적값(acc): ${acc}, 현재값(cur): ${cur}`);
return acc + cur;
}, 0);
이 예시의 실행과정은 이렇게 된다.
// 실행 과정:
// 1단계: acc: 0, cur: 1 => 반환값: 1
// 2단계: acc: 1, cur: 2 => 반환값: 3
// 3단계: acc: 3, cur: 3 => 반환값: 6
// 4단계: acc: 6, cur: 4 => 반환값: 10
// 5단계: acc: 10, cur: 5 => 반환값: 15
그래서 결국 sum의 결과값은 15가 된다.
console.log(sum); // 15
초기값을 주지 않는 경우 예시
// 2. 초기값을 주지 않는 경우
const numbers2 = [1, 2, 3, 4, 5];
const sum2 = numbers2.reduce((acc, cur) => {
console.log(`누적값(acc): ${acc}, 현재값(cur): ${cur}`);
return acc + cur;
}); // 초기값 없음
실행 과정은 이렇게 진행된다.
// 실행 과정:
// 1단계: acc: 1, cur: 2 => 반환값: 3 (첫 번째 값이 초기값이 됨), 첫번째가 초기값이 되고 현재값은 2부터 시작함(두번째)
// 2단계: acc: 3, cur: 3 => 반환값: 6
// 3단계: acc: 6, cur: 4 => 반환값: 10
// 4단계: acc: 10, cur: 5 => 반환값: 15
다양한 활용 예시
1. 최대값 찾기
const numbers = [4, 1, 9, 2, 5];
const max = numbers.reduce((acc, cur) => {
console.log(`현재 누적값: ${acc}, 현재값: ${cur}, 비교 후 큰 값: ${Math.max(acc, cur)}`);
return Math.max(acc, cur);
}, 0);
// 실행 과정:
// 1단계: acc: 0, cur: 4
// Math.max(0, 4) => 4가 더 크니까 4 반환
// 2단계: acc: 4, cur: 1
// Math.max(4, 1) => 4가 더 크니까 4 반환
// 3단계: acc: 4, cur: 9
// Math.max(4, 9) => 9가 더 크니까 9 반환
// 4단계: acc: 9, cur: 2
// Math.max(9, 2) => 9가 더 크니까 9 반환
// 5단계: acc: 9, cur: 5
// Math.max(9, 5) => 9가 더 크니까 9 반환
console.log(max); // 9
2. 객체 배열에서 특정 값 합계 구하기
const cart = [
{ item: '사과', price: 1000 },
{ item: '바나나', price: 2000 },
{ item: '딸기', price: 3000 }
];
const totalPrice = cart.reduce((acc, cur) => {
return acc + cur.price;
}, 0);
console.log(totalPrice); // 6000
3. 배열을 객체로 반환하기
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana'];
const fruitCount = fruits.reduce((acc, cur) => {
// 현재 과일이 없으면 1, 있으면 기존 값에 1을 더함
acc[cur] = (acc[cur] || 0) + 1;
return acc;
}, {});
console.log(fruitCount);
// { apple: 2, banana: 2, orange: 1 }
더 상세히 적어보기
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana'];
const fruitCount = fruits.reduce((acc, cur) => {
console.log('현재 상태:', {
누적객체: acc,
현재과일: cur,
해당과일현재개수: acc[cur],
});
acc[cur] = (acc[cur] || 0) + 1;
console.log('업데이트 후:', acc);
console.log('------------------------');
return acc;
}, {}); // 초기값으로 빈 객체 {}를 줌
// 실행 과정:
// 1단계: cur = 'apple'
// acc = {}
// acc['apple'] = (undefined || 0) + 1 = 1
// 결과: { apple: 1 }
// 2단계: cur = 'banana'
// acc = { apple: 1 }
// acc['banana'] = (undefined || 0) + 1 = 1
// 결과: { apple: 1, banana: 1 }
// 3단계: cur = 'apple'
// acc = { apple: 1, banana: 1 }
// acc['apple'] = (1 || 0) + 1 = 2
// 결과: { apple: 2, banana: 1 }
// 4단계: cur = 'orange'
// acc = { apple: 2, banana: 1 }
// acc['orange'] = (undefined || 0) + 1 = 1
// 결과: { apple: 2, banana: 1, orange: 1 }
// 5단계: cur = 'banana'
// acc = { apple: 2, banana: 1, orange: 1 }
// acc['banana'] = (1 || 0) + 1 = 2
// 결과: { apple: 2, banana: 2, orange: 1 }
// 다른 방식으로 작성한 동일한 로직
function countFruits(fruits) {
const result = {};
for (const fruit of fruits) {
if (result[fruit]) {
// 이미 과일이 있으면 개수 증가
result[fruit] += 1;
} else {
// 처음 나온 과일이면 1로 초기화
result[fruit] = 1;
}
}
return result;
}
// 조건부 연산자(||)를 사용하는 이유 설명
const obj = {};
console.log(obj.apple); // undefined
console.log(undefined || 0); // 0 (undefined면 0 사용)
console.log(1 || 0); // 1 (값이 있으면 그 값 사용)
4. 평균값 찾기
const reviews = [
{ rating: 5, text: "아주 좋아요" },
{ rating: 4, text: "괜찮아요" },
{ rating: 5, text: "최고에요" }
];
const averageRating = reviews.reduce((acc, cur) => {
return acc + cur.rating;
}, 0) / reviews.length;
console.log(averageRating); // 4.666...
const reviews = [
{ rating: 5, text: "아주 좋아요" },
{ rating: 4, text: "괜찮아요" },
{ rating: 5, text: "최고에요" }
];
const averageRating = reviews.reduce((acc, cur) => {
console.log('현재 상태:', {
현재까지의합계: acc,
현재리뷰: cur,
현재평점: cur.rating
});
const sum = acc + cur.rating;
console.log('더한 후:', sum);
console.log('------------------------');
return sum;
}, 0) / reviews.length; // 마지막에 리뷰 개수로 나눔
// 실행 과정:
// 1단계
// acc (초기값) = 0
// cur = { rating: 5, text: "아주 좋아요" }
// 0 + 5 = 5
// 2단계
// acc = 5 (이전 단계의 결과)
// cur = { rating: 4, text: "괜찮아요" }
// 5 + 4 = 9
// 3단계
// acc = 9 (이전 단계의 결과)
// cur = { rating: 5, text: "최고에요" }
// 9 + 5 = 14
// 최종 계산
// 전체 합계 = 14
// 리뷰 개수 = 3
// 평균 = 14 / 3 = 4.666...
// for 문으로 작성한 동일한 로직
function calculateAverage(reviews) {
let sum = 0;
// 합계 계산
for (const review of reviews) {
sum += review.rating;
}
// 평균 계산
return sum / reviews.length;
}
// 소수점 자리 제한하고 싶다면
const roundedAverage = Number(averageRating.toFixed(1)); // 4.7
// 다양한 활용 예시
const reviewStats = reviews.reduce((acc, cur) => {
return {
sum: acc.sum + cur.rating,
count: acc.count + 1,
min: Math.min(acc.min, cur.rating),
max: Math.max(acc.max, cur.rating)
};
}, { sum: 0, count: 0, min: 5, max: 0 });
console.log({
평균: reviewStats.sum / reviewStats.count,
최저평점: reviewStats.min,
최고평점: reviewStats.max
});