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

JavaScript에서 배열 안의 중복된 하위 배열을 필터링하는 방법

문제 상황

다음과 같이 동일한 구조의 하위 배열이 여러 번 반복되어 포함된 2차원 배열이 있다고 가정해 보겠습니다.

const arr = [
    [
        "Serta",
        "Black Friday"
    ],
    [
        "Serta",
        "Black Friday"
    ],
    [
        "Simmons",
        "Black Friday"
    ],
    [
        "Simmons",
        "Black Friday"
    ],
    [
        "Simmons",
        "Black Friday"
    ],
    [
        "Simmons",
        "Black Friday"
    ]
];

여기서 요구되는 것은 이러한 배열을 입력으로 받아, 원본 배열에 존재하는 고유한(unique) 하위 배열만 담고 있는 새로운 배열을 반환하는 JavaScript 함수를 작성하는 것입니다.

해결 방법: JSON.stringify와 filter 활용

배열은 참조 타입이기 때문에 === 연산자나 indexOf로는 값이 같아도 서로 다른 객체로 판단됩니다. 따라서 각 하위 배열을 JSON.stringify()로 문자열로 직렬화한 뒤, 이 문자열을 키로 사용해 이미 등장했는지 여부를 추적하면 손쉽게 중복을 걸러낼 수 있습니다.

const arr = [
    ["Serta", "Black Friday"],
    ["Serta", "Black Friday"],
    ["Simmons", "Black Friday"],
    ["Simmons", "Black Friday"],
    ["Simmons", "Black Friday"],
    ["Simmons", "Black Friday"]
];

const filterCommon = arr => {
    const map = Object.create(null);
    const res = arr.filter(el => {
        const str = JSON.stringify(el);
        const bool = !map[str]; // 처음 등장한 배열인지 확인
        map[str] = true;
        return bool;
    });
    return res;
};

console.log(filterCommon(arr));

실행 결과

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

[ [ 'Serta', 'Black Friday' ], [ 'Simmons', 'Black Friday' ] ]

동작 원리 정리

  • Object.create(null)로 프로토타입이 없는 순수한 맵 객체를 생성하여 키 충돌 위험을 없앱니다.
  • filter()가 각 하위 배열을 순회할 때마다 해당 배열을 문자열로 변환합니다.
  • 맵에 아직 존재하지 않는 키라면 처음 등장한 고유한 배열이므로 결과에 포함됩니다.
  • 이미 존재하는 키라면 중복이므로 false를 반환해 제외됩니다.

참고: Set을 활용한 대안

ES6의 Set을 사용하면 같은 로직을 더 간결하게 표현할 수도 있습니다.

const filterCommon = arr => {
    const seen = new Set();
    return arr.filter(el => {
        const str = JSON.stringify(el);
        if (seen.has(str)) return false;
        seen.add(str);
        return true;
    });
};

두 방식 모두 시간 복잡도는 O(n)으로 효율적이며, 하위 배열의 요소 순서까지 완전히 동일한 경우에만 중복으로 처리한다는 점을 유의하시기 바랍니다.