문제 정의
여러 스포츠 종목에 참가한 선수들의 점수를 담은 배열이 있다고 가정해 보겠습니다. 각 객체는 종목명(sport)과 선수별 점수를 키-값 쌍으로 저장하고 있으며, 데이터는 다음과 같이 표현됩니다.
const scores = [
{sport: 'cricket', aman: 54, vishal: 65, jay: 43, hardik: 88, karan:23},
{sport: 'soccer', aman: 14, vishal: 75, jay: 41, hardik: 13, karan:73},
{sport: 'hockey', aman: 43, vishal: 35, jay: 53, hardik: 43, karan:29},
{sport: 'volleyball', aman: 76, vishal: 22, jay: 36, hardik: 24, karan:47},
{sport: 'baseball', aman: 87, vishal: 57, jay: 48, hardik: 69, karan:37},
];
이 배열을 입력받아 sport 키의 값은 'all'로 설정하고, 나머지 선수 키에는 배열 내 각 객체에 흩어져 있는 점수들의 합계가 담긴 단일 객체를 반환하는 함수를 작성하는 것이 목표입니다.
reduce() 메서드로 해결하기
이런 문제는 Array.prototype.reduce() 메서드를 사용하면 가장 깔끔하게 처리할 수 있습니다. reduce()는 배열을 순회하면서 결과를 누산기(accumulator)에 계속 누적하기 때문에, 여러 객체에 분산된 숫자 값을 하나로 합산하는 작업에 특히 적합합니다.
함수의 전체 코드는 다음과 같습니다.
const scores = [
{sport: 'cricket', aman: 54, vishal: 65, jay: 43, hardik: 88, karan:23},
{sport: 'soccer', aman: 14, vishal: 75, jay: 41, hardik: 13, karan:73},
{sport: 'hockey', aman: 43, vishal: 35, jay: 53, hardik: 43, karan:29},
{sport: 'volleyball', aman: 76, vishal: 22, jay: 36, hardik: 24, karan:47},
{sport: 'baseball', aman: 87, vishal: 57, jay: 48, hardik: 69, karan:37},
];
const sumScores = (arr) => {
return arr.reduce((acc, val) => {
Object.keys(val).forEach(key => {
if(key !== 'sport'){
acc[key] = (acc[key] || 0) + val[key];
}
});
return acc;
}, { sport: 'all' });
};
console.log(sumScores(scores));
코드 동작 원리
- 초기값 지정: reduce()의 두 번째 인자로
{ sport: 'all' }을 전달하여 누산기를 초기화합니다. 초기값을 명시하면 첫 번째 요소부터 안전하게 합산을 시작할 수 있어 오류를 예방할 수 있습니다. - 키 순회:
Object.keys(val)로 현재 객체의 모든 키를 가져옵니다. - sport 제외: sport 키는 문자열 값이므로 합산 대상에서 제외합니다.
- 점수 누적:
(acc[key] || 0) + val[key]로 각 선수의 점수를 누적합니다. 해당 키가 아직 없으면 0부터 더하므로, 선수 구성이 객체마다 달라도 유연하게 대응할 수 있습니다.
실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
{
sport: 'all',
aman: 274,
vishal: 254,
jay: 221,
hardik: 237,
karan: 209
}
결과를 보면 sport 키는 'all'로 설정되었고, 각 선수의 점수는 크리켓, 축구, 하키, 배구, 야구 5개 종목 점수의 합으로 정확하게 계산된 것을 확인할 수 있습니다. 이 패턴은 키가 고정되어 있지 않은 동적 객체 배열의 합계를 구할 때 널리 활용되므로, 실무에서도 유용하게 응용할 수 있습니다.