리터럴 값으로 구성된 2차원 배열을 입력받아 처리하는 JavaScript 함수를 작성해야 하는 상황을 가정해 보겠습니다.
이 함수는 원본 배열의 모든 요소를 그대로 유지하되, 앞서 이미 등장했던 중복 값은 제거한 새로운 배열을 반환해야 합니다. 즉, 각 값은 전체 배열에서 딱 한 번만 나타나도록 만드는 것입니다.
예제
이를 구현한 코드는 다음과 같습니다.
const arr = [
[1,2,3,4,5],
[3,4,6,7,8,2],
[7,2,4,9,11,15],
[10,12,3,7,11]
];
const removeDuplicates = arr => {
let map = {};
let res = [];
res = arr.map(el => {
return el.filter(val => {
if(map[val]){
return false;
};
map[val] = 1;
return true;
});
});
return res;
};
console.log(removeDuplicates(arr));출력 결과
콘솔에 출력되는 결과는 다음과 같습니다.
[ [ 1, 2, 3, 4, 5 ], [ 6, 7, 8 ], [ 9, 11, 15 ], [ 10, 12 ] ]
코드 동작 원리
이 코드가 어떻게 작동하는지 단계별로 살펴보겠습니다.
1. 객체를 활용한 값 추적
map이라는 빈 객체를 생성하여 이미 등장한 값을 기록합니다. JavaScript에서 객체 속성 접근은 해시 기반으로 동작하기 때문에 조회 속도가 매우 빠르며, 중복 검사에 특히 효율적입니다.
2. map과 filter 메서드의 조합
외부의 map() 메서드는 각 하위 배열을 순차적으로 순회하고, 내부의 filter() 메서드는 해당 하위 배열의 개별 값을 하나씩 검사합니다.
3. 중복 판별 로직
filter의 콜백 함수 안에서 현재 값이 map 객체에 이미 존재하는지 확인합니다. 값이 존재하면 false를 반환하여 해당 값을 결과에서 제외하고, 존재하지 않으면 map 객체에 값을 기록한 뒤 true를 반환하여 값을 유지합니다.
그 결과 첫 번째 하위 배열의 모든 값은 그대로 유지되며, 두 번째 배열부터는 이전 배열에서 이미 등장한 값들(예: 3, 4, 2)이 자동으로 걸러져 나갑니다. 최종 출력에서 확인할 수 있듯이, 두 번째 배열은 [6, 7, 8]만 남고 세 번째 배열은 [9, 11, 15], 네 번째 배열은 [10, 12]만 남게 됩니다.
이 방식은 시간 복잡도 면에서도 유리하여, 배열의 크기가 커져도 안정적으로 동작한다는 장점이 있습니다.