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

JavaScript로 두 배열의 대칭 차집합(차이점) 구하는 방법

문제 상황

두 개의 숫자 배열이 다음과 같이 주어졌다고 가정해 보겠습니다.

const arr1 = [12, 54, 2, 4, 6, 34, 3];
const arr2 = [54, 2, 5, 12, 4, 1, 3, 34];

두 배열 중 한쪽에만 존재하고 양쪽 모두에는 속하지 않는 요소, 즉 수학적으로 말하는 대칭 차집합(symmetric difference)에 해당하는 값들을 반환하는 JavaScript 함수를 작성해야 합니다.

위 예시에서 두 배열에 공통으로 포함된 숫자는 12, 54, 2, 4, 3, 34입니다. 따라서 최종 결과에는 첫 번째 배열에만 있는 6과 두 번째 배열에만 있는 5, 1이 포함되어야 합니다.

구현 코드

다음은 이 문제를 해결하는 전체 코드입니다.

const arr1 = [12, 54, 2, 4, 6, 34, 3];
const arr2 = [54, 2, 5, 12, 4, 1, 3, 34];

const difference = (first, second) => {
   const res = [];
   // 첫 번째 배열에서 두 번째 배열에 없는 요소 추출
   for(let i = 0; i < first.length; i++){
      if(second.indexOf(first[i]) === -1){
         res.push(first[i]);
      }
   }
   // 두 번째 배열에서 첫 번째 배열에 없는 요소 추출
   for(let j = 0; j < second.length; j++){
      if(first.indexOf(second[j]) === -1){
         res.push(second[j]);
      }
   }
   return res;
};

console.log(difference(arr1, arr2));

출력 결과

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

[ 6, 5, 1 ]

동작 원리

이 함수의 핵심 로직은 다음과 같습니다.

  • indexOf() 메서드는 특정 요소가 배열에 존재하지 않으면 -1을 반환합니다. 이 특성을 이용해 두 배열 간의 포함 여부를 판별합니다.
  • 첫 번째 반복문에서는 first 배열의 각 요소가 second 배열에 없는지 확인하고, 없다면 결과 배열에 추가합니다.
  • 두 번째 반복문에서는 반대로 second 배열의 요소가 first 배열에 없는 경우를 찾아 추가합니다.
  • 최종적으로 두 배열의 교집합을 제외한 모든 고유 요소가 담긴 배열이 반환됩니다.

더 간결한 방법: filter 활용

filter()includes() 메서드를 조합하면 동일한 로직을 훨씬 간결하게 표현할 수 있습니다.

const difference = (first, second) =>
   [...first.filter(el => !second.includes(el)),
    ...second.filter(el => !first.includes(el))];

console.log(difference(arr1, arr2)); // [ 6, 5, 1 ]

이 방식은 가독성이 뛰어나고 함수형 프로그래밍 스타일에 잘 어울립니다. 다만 배열의 크기가 매우 클 경우 includes()가 내부적으로 선형 탐색을 수행하기 때문에, Set 객체로 변환하여 조회 시간을 O(1)로 줄이는 최적화를 함께 고려해 보는 것이 좋습니다.