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

JavaScript로 두 배열의 편차(차집합) 요소 구하는 방법

문제 소개

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

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

여기서 우리가 작성해야 할 함수는 두 배열을 인자로 받아, 양쪽 배열에 공통으로 존재하지 않는 요소들, 즉 한쪽 배열에만 있는 값들을 모아서 반환하는 것입니다. 이를 흔히 '편차' 또는 '대칭 차집합'이라고 부릅니다.

해결 로직

구현 아이디어는 매우 단순합니다.

  • 첫 번째 배열을 순회하면서, 해당 요소가 두 번째 배열에 없다면 결과 배열에 추가합니다.
  • 두 번째 배열을 순회하면서, 해당 요소가 첫 번째 배열에 없다면 결과 배열에 추가합니다.

특정 요소가 배열에 포함되어 있는지 확인할 때는 indexOf() 메서드를 사용할 수 있습니다. indexOf()는 요소를 찾지 못하면 -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 ]

숫자 6은 첫 번째 배열에만 존재하고, 51은 두 번째 배열에만 존재하기 때문에 정확히 이 세 개의 값이 결과로 반환됩니다.

filter()를 활용한 더 간결한 방법

ES6 이상 환경이라면 filter() 메서드와 전개 연산자(spread operator)를 조합해 훨씬 간결하게 표현할 수도 있습니다.

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

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

두 방식 모두 동일한 결과를 반환하지만, filter() 기반 코드는 반복문과 임시 변수 없이 의도를 명확하게 드러내므로 가독성 면에서 유리합니다. 다만 배열 크기가 매우 클 경우 성능을 고려해 Set 객체로 조회 시간을 줄이는 최적화도 가능합니다.