문제 개요
중복된 값이 포함된 숫자 배열이 주어졌을 때, 동일한 값을 가진 요소들을 하나의 인덱스로 병합하여 합계를 계산하는 JavaScript 함수를 작성해 보겠습니다.
예를 들어 입력 배열이 다음과 같다고 가정해 봅시다.
const input = [1, 3, 1, 3, 5, 7, 5, 4];
출력
결과는 다음과 같아야 합니다.
const output = [2, 6, 10, 7, 4];
- 중복된 1은 인덱스 0에 합산됩니다 (1 + 1 = 2)
- 중복된 3은 인덱스 1에 합산됩니다 (3 + 3 = 6)
- 중복된 5는 합산되고(5 + 5 = 10), 한 번만 등장하는 7과 4는 그대로 유지됩니다
접근 방법
이 문제는 두 단계로 해결할 수 있습니다.
- 빈도 계산:
reduce()메서드와Map객체를 사용해 각 숫자가 몇 번 등장하는지 집계합니다. - 합계 변환: Map의 각 항목에 대해 '값 × 등장 횟수'를 곱한 결과로 새로운 배열을 생성합니다.
구현 코드
const input = [1, 3, 1, 3, 5, 7, 5, 4];
const mergeDuplicates = arr => {
// 각 요소의 등장 횟수를 Map에 기록
const map = arr.reduce((acc, val) => {
if(acc.has(val)){
acc.set(val, acc.get(val) + 1);
}else{
acc.set(val, 1);
};
return acc;
}, new Map());
// 값 × 등장 횟수로 새 배열 생성
return Array.from(map, el => el[0] * el[1]);
};
console.log(mergeDuplicates(input));실행 결과
콘솔에 출력되는 결과는 다음과 같습니다.
[ 2, 6, 10, 7, 4 ]
코드 설명
reduce() 콜백 함수는 배열을 순회하면서 Map 객체(acc)에 각 값의 등장 횟수를 누적합니다. 이미 존재하는 값이라면 기존 카운트에 1을 더하고, 처음 등장한 값이라면 1로 설정합니다.
이후 Array.from(map, el => el[0] * el[1])은 Map의 각 [키, 값] 쌍을 받아 키(숫자 자체)와 값(등장 횟수)을 곱한 새 배열을 반환합니다. Map은 삽입 순서를 유지하므로, 결과 배열은 원본 배열에서 각 값이 처음 등장한 순서대로 정렬됩니다.
이 방식은 배열을 단 한 번만 순회하므로 시간 복잡도가 O(n)이며, 대용량 데이터에서도 효율적으로 동작한다는 장점이 있습니다.