Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript에서 정렬 없이 배열의 고유 요소 개수 구하는 방법

배열을 다루다 보면 중복된 값이 포함된 배열에서 고유(unique)한 요소가 몇 개인지 세어야 하는 경우가 자주 있습니다. 이번 글에서는 정렬 없이 간단하게 고유 요소의 개수를 구하는 방법을 알아보겠습니다.

예를 들어, 다음과 같이 중복 값이 섞여 있는 문자열 배열이 있다고 가정해 봅시다.

const arr = ['Cat', 'Dog', 'Cat', 'Elephant', 'Dog', 'Grapes', 'Dog', 'Lion', 'Grapes', 'Lion'];

접근 방식

이 배열에는 'Cat' 2개, 'Dog' 3개, 'Elephant' 1개, 'Grapes' 2개, 'Lion' 2개가 들어 있으므로, 고유한 요소는 총 5개입니다.

배열을 미리 정렬하지 않고도 Array.prototype.reduce()Array.prototype.lastIndexOf()를 조합하면 손쉽게 개수를 구할 수 있습니다.

  • reduce(): 배열을 순회하면서 누적값(acc)으로 고유 요소의 개수를 쌓아갑니다.
  • lastIndexOf(): 현재 요소의 마지막 등장 인덱스를 반환합니다. 현재 순회 중인 인덱스와 일치한다면, 해당 요소는 배열 전체에서 단 한 번만 등장했다는 의미이므로 카운트를 1 증가시킵니다.

코드 예제

const arr = ['Cat', 'Dog', 'Cat', 'Elephant', 'Dog', 'Grapes', 'Dog',
'Lion', 'Grapes', 'Lion'];

const countUnique = arr => {
    return arr.reduce((acc, val, ind, array) => {
        // 현재 요소의 마지막 등장 위치가 현재 인덱스와 같으면 고유 요소
        if(array.lastIndexOf(val) === ind){
            return ++acc;
        }
        return acc;
    }, 0);
};

console.log(countUnique(arr));

실행 결과

위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.

5

동작 원리 살펴보기

이 코드의 핵심은 array.lastIndexOf(val) === ind라는 조건입니다. 예를 들어 첫 번째 'Cat'(인덱스 0)의 경우 lastIndexOf('Cat')은 2를 반환하므로 조건이 false가 되어 카운트되지 않습니다. 반면 'Elephant'(인덱스 3)처럼 한 번만 등장하는 요소는 마지막 등장 위치가 자기 자신이므로 카운트됩니다.

참고: 성능과 대안

lastIndexOf()는 매번 배열을 끝까지 탐색하므로 시간 복잡도가 O(n²)입니다. 따라서 대용량 데이터에서는 Set 객체를 활용하는 것이 더 효율적입니다.

const countUnique = arr => new Set(arr).size;
console.log(countUnique(arr)); // 5

new Set(arr)은 중복을 자동으로 제거하고, .size로 그 개수를 바로 얻을 수 있어 코드도 더 간결해집니다. 상황에 맞게 두 방법 중 적절한 것을 선택하시기 바랍니다.