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

JavaScript로 두 배열에서 공통되지 않은 요소만 추출하기

두 개의 숫자 배열이 있다고 가정해 보겠습니다.

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

위 배열을 살펴보면 6은 첫 번째 배열(arr1)에만 존재하고, 51은 두 번째 배열(arr2)에만 존재합니다. 나머지 요소들은 두 배열 모두에 공통으로 포함되어 있습니다.

이번 글에서는 이처럼 두 개의 배열을 인수로 받아, 양쪽 배열에 공통으로 존재하지 않는 요소들만 골라 새로운 배열로 반환하는 JavaScript 함수를 작성해 보겠습니다.

구현 아이디어

핵심 로직은 다음과 같습니다.

  • 첫 번째 배열을 순회하면서 각 요소가 두 번째 배열에 존재하는지 indexOf()로 확인합니다. 결과가 -1이면 해당 요소는 두 번째 배열에 없다는 뜻이므로 결과 배열에 추가합니다.
  • 같은 방식으로 두 번째 배열을 순회하며 첫 번째 배열에 없는 요소를 결과 배열에 추가합니다.
  • 모든 순회가 끝나면 결과 배열을 반환합니다.

예제 코드

다음은 전체 구현 코드입니다.

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

const unCommonArray = (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(unCommonArray(arr1, arr2));

실행 결과

콘솔에 출력되는 결과는 다음과 같습니다.

[ 6, 5, 1 ]

arr1에만 있는 6, arr2에만 있는 51이 정확히 추출된 것을 확인할 수 있습니다.

더 간결한 대안: filter() 활용

ES6의 filter()와 스프레드 연산자를 사용하면 같은 로직을 훨씬 간결하게 표현할 수 있습니다.

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

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

filter()는 조건을 만족하는 요소만 남긴 새 배열을 반환하므로, 반복문과 push()를 직접 작성할 필요 없이 선언형으로 깔끔하게 처리됩니다. 가독성 면에서는 이 방식이 더 권장됩니다.

정리

두 배열의 대칭 차집합(symmetric difference), 즉 한쪽에만 존재하는 요소를 구하는 문제는 반복문 + indexOf() 조합 또는 filter() + includes() 조합으로 손쉽게 해결할 수 있습니다. 단, 두 방식 모두 내부적으로 배열을 선형 탐색하므로 시간 복잡도는 O(n×m)입니다. 배열의 크기가 매우 크다면 Set 객체를 활용해 조회 성능을 O(1)로 개선하는 방법도 고려해볼 만합니다.