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

JavaScript 배열에서 중복된 요소를 완전히 제거하는 방법

리터럴 값(숫자, 문자열 등)으로 구성된 배열을 입력받아 처리하는 JavaScript 함수를 작성해야 합니다.

입력받은 배열에는 동일한 값이 여러 번 나타나는 경우가 있을 수 있습니다. 이때 함수는 단순히 중복을 정리하는 것이 아니라, 한 번이라도 반복해서 등장한 값은 해당 요소의 모든 인스턴스를 배열에서 완전히 제거해야 합니다.

예를 들어 배열에 숫자 2가 두 번 포함되어 있다면, 결과 배열에는 2가 하나만 남는 것이 아니라 아예 존재하지 않아야 합니다.

해결 접근 방식

핵심 아이디어는 간단합니다. 어떤 값이 배열에서 딱 한 번만 등장했다면, 그 값의 첫 번째 인덱스(indexOf)와 마지막 인덱스(lastIndexOf)가 서로 같습니다. 반대로 두 인덱스가 다르다면 그 값은 두 번 이상 등장한 중복 요소이므로 필터링 대상이 됩니다.

JavaScript의 filter() 메서드를 사용하면 이 조건을 깔끔하게 구현할 수 있습니다.

예제 코드

const arr = [1, 2, 3, 2, 4];

const removeAllInstances = (arr = []) => {
    const filtered = arr.filter(val => {
        const lastIndex = arr.lastIndexOf(val);
        const firstIndex = arr.indexOf(val);
        // 첫 인덱스와 마지막 인덱스가 같으면 한 번만 등장한 값
        return lastIndex === firstIndex;
    });
    return filtered;
};

console.log(removeAllInstances(arr));

출력 결과

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

[ 1, 3, 4 ]

코드 설명

입력 배열 [1, 2, 3, 2, 4]에서 숫자 2는 인덱스 1과 3, 두 곳에서 등장합니다. 따라서 indexOf(2)는 1을, lastIndexOf(2)는 3을 반환하므로 두 값이 일치하지 않고, 필터 조건을 통과하지 못해 제거됩니다.

반면 1, 3, 4는 각각 한 번만 등장하기 때문에 첫 인덱스와 마지막 인덱스가 동일하여 최종 결과 배열에 그대로 유지됩니다.

참고: 성능 개선 팁

위 방식은 간단하지만, 요소마다 indexOflastIndexOf를 호출하므로 시간 복잡도가 O(n²)입니다. 배열 크기가 클 경우 Map이나 객체를 이용해 각 값의 등장 횟수를 먼저 세고(O(n)), 등장 횟수가 1인 값만 남기면 O(n)으로 최적화할 수 있습니다.

const removeAllInstancesOptimized = (arr = []) => {
    const countMap = new Map();
    arr.forEach(val => countMap.set(val, (countMap.get(val) || 0) + 1));
    return arr.filter(val => countMap.get(val) === 1);
};

console.log(removeAllInstancesOptimized([1, 2, 3, 2, 4])); // [ 1, 3, 4 ]