배열 리터럴을 인자로 받아, 그 배열 안에서 가장 많이 등장하는 요소가 몇 번 나타나는지 그 횟수를 반환하는 JavaScript 함수를 작성해야 합니다.
예를 들어 다음과 같은 배열이 주어졌다고 가정해 보겠습니다.
let arr = [2, 8, 4, 8, 6, 4, 7, 8];
이 배열에서 가장 자주 등장하는 값은 8이며 총 3번 나타나므로, 함수는 3을 반환해야 합니다.
예제 코드
reduce() 메서드로 각 요소의 등장 횟수를 객체에 집계한 뒤, Math.max()로 그중 최댓값을 구하는 방식으로 문제를 해결할 수 있습니다.
let arr = [2, 8, 4, 8, 6, 4, 7, 8];
const countOccurence = arr => {
// 각 요소의 등장 횟수를 객체에 누적 집계
const frequency = arr.reduce((acc, val) => {
acc[val] = (acc[val] || 0) + 1;
return acc;
}, {});
// 등장 횟수 중 가장 큰 값을 반환
return Math.max(...Object.values(frequency));
};
console.log(countOccurence(arr));
출력 결과
콘솔에 출력되는 결과는 다음과 같습니다.
3
코드 동작 원리
1단계 — 빈도수 집계: reduce()를 사용해 배열을 순회하면서 각 값이 몇 번 등장했는지 객체 frequency에 누적합니다. 이때 acc[val] || 0 처리 덕분에 해당 값이 처음 등장했을 때 undefined 대신 0부터 카운트가 시작됩니다.
2단계 — 최댓값 추출: Object.values(frequency)로 빈도수만 모은 배열 [1, 3, 2, 1, 1]을 만들고, 전개 연산자(...)와 함께 Math.max()에 전달해 가장 큰 값인 3을 얻습니다.
주의: 단순 '최댓값 개수 세기' 접근의 함정
배열의 최댓값을 먼저 구한 후 filter()로 그 값과 같은 요소만 골라 개수를 세는 방식도 떠올릴 수 있습니다. 하지만 이 방법은 "최댓값 = 최빈값"이라는 보장이 없기 때문에 일반적인 경우 올바른 답을 내지 못합니다. 예를 들어 [1, 1, 1, 9]처럼 최빈값(1, 3번 등장)과 최댓값(9, 1번 등장)이 서로 다른 배열에서는 엉뚱한 결과가 나옵니다. 따라서 위 예제처럼 빈도수를 직접 집계하는 방식이 더 안전하고 범용적인 해결책입니다.