배열이 주어졌을 때, 배열에 포함된 모든 고유한(distinct) 값을 한 번씩만 더해 총합을 구하는 함수를 작성해 보겠습니다.
예를 들어 다음과 같은 숫자 배열이 있다고 가정해 봅시다.
const arr = [1, 5, 2, 1, 2, 3, 4, 5, 7, 8, 7, 1];
이 배열에서 중복을 제거하면 [1, 5, 2, 3, 4, 7, 8]이 되고, 이 값들의 합은 다음과 같습니다.
1 + 5 + 2 + 3 + 4 + 7 + 8 = 30
구현 방법
가장 직관적인 방법은 각 요소에 대해 해당 값이 마지막으로 등장하는 인덱스(lastIndexOf)와 현재 인덱스가 일치하는지 확인하는 것입니다. 이 조건을 만족하는 경우에만 값을 더하면, 각 고유한 값이 정확히 한 번씩 합산됩니다.
다음은 전체 코드입니다.
const arr = [1, 5, 2, 1, 2, 3, 4, 5, 7, 8, 7, 1];
const distinctSum = arr => {
let res = 0;
for (let i = 0; i < arr.length; i++) {
// 현재 인덱스가 해당 값의 마지막 등장 위치라면 한 번만 더한다
if (i === arr.lastIndexOf(arr[i])) {
res += arr[i];
}
}
return res;
};
console.log(distinctSum(arr));
출력 결과
콘솔에는 다음과 같이 출력됩니다.
30
대안: Set을 활용한 간결한 방법
ES6의 Set 객체를 사용하면 코드를 훨씬 간결하게 만들 수 있습니다. Set은 중복을 허용하지 않으므로, 배열을 Set으로 변환한 뒤 reduce()로 합계를 구하면 됩니다.
const distinctSum = arr =>
[...new Set(arr)].reduce((sum, num) => sum + num, 0);
console.log(distinctSum([1, 5, 2, 1, 2, 3, 4, 5, 7, 8, 7, 1])); // 30
Set을 활용한 방식은 가독성이 좋고 의도가 명확하다는 장점이 있으며, lastIndexOf를 사용하는 방식은 별도의 자료구조 없이 원본 배열만으로 해결할 수 있다는 점이 특징입니다. 상황에 맞게 두 방식 중 하나를 선택해 사용하면 됩니다.