JavaScript 개발을 하다 보면 한 배열에서 다른 배열에 포함된 요소들을 제거해야 하는 경우가 자주 발생합니다. 이번 글에서는 filter() 메서드를 활용해 두 배열의 차집합을 구하는 방법을 예제와 함께 살펴보겠습니다.
문제 상황
다음과 같이 두 개의 배열이 있다고 가정해 보겠습니다.
const arr1 = [4, 23, 7, 6, 3, 6, 4, 3, 56, 4]; const arr2 = [4, 56, 23];
목표는 첫 번째 배열(arr1)에서 두 번째 배열(arr2)에 포함된 요소를 모두 제거하고, 나머지 요소들만 담은 새로운 배열을 반환하는 것입니다. 즉, 기대하는 실행 결과는 다음과 같습니다.
const output = [7, 6, 3, 6, 3];
filter() 메서드로 구현하기
Array.prototype.filter()는 콜백 함수가 true를 반환하는 요소들만 모아 새로운 배열을 만들어 주는 고차 함수입니다. 여기에 indexOf()를 함께 사용하면 특정 배열에 존재하지 않는 요소만 손쉽게 걸러낼 수 있습니다.
예제 코드
const arr1 = [4, 23, 7, 6, 3, 6, 4, 3, 56, 4];
const arr2 = [4, 56, 23];
const filterArray = (arr1, arr2) => {
const filtered = arr1.filter(el => {
return arr2.indexOf(el) === -1;
});
return filtered;
};
console.log(filterArray(arr1, arr2));
실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
[ 7, 6, 3, 6, 3 ]
동작 원리
핵심 로직을 단계별로 살펴보면 다음과 같습니다.
1. filter()가 arr1의 요소를 하나씩 순회하며 콜백 함수를 호출합니다.
2. arr2.indexOf(el)는 el이 arr2에 존재하면 해당 인덱스를, 존재하지 않으면 -1을 반환합니다.
3. 따라서 '=== -1' 조건은 "arr2에 존재하지 않는 요소"만 통과시키는 역할을 합니다.
4. 조건을 통과한 요소들만 모아 새로운 배열을 생성한 뒤 반환합니다.
참고: includes()를 활용한 더 간결한 방법
ES2016부터 지원되는 includes() 메서드를 사용하면 코드를 더욱 간결하게 작성할 수 있습니다.
const filterArray = (arr1, arr2) => arr1.filter(el => !arr2.includes(el));
includes()는 단순히 값의 존재 여부만 확인하므로, 인덱스 정보가 필요하지 않은 경우에는 indexOf()보다 훨씬 직관적이고 가독성이 좋습니다. 상황에 맞게 두 방법을 적절히 활용해 보세요.