[javascript] 자바스크립트 배열의 중복을 제거하는 방법 총정리

배열 요소에 중복이 있으면 안 되는 경우, 자바스크립트는 중복이 있는지를 확인해서 제거할 수 있는 여러 가지 방법을 제공합니다. 각각의 방법이 장단점이 있기 때문에 경우에 따라 적당한 중복 제거 방법을 사용하는 것이 좋습니다.

필터(Filter)로 배열 중복 제거

배열의 내장 메서드인 filter()를 이용해서 조건에 맞는 요소만을 반환받는 방식으로 중복 없는 배열을 만들 수 있습니다.

필터 메서드는 배열 요소의 선택 조건을 직접 정할 수 있기 때문에 중복 제거가 아니어도 다양한 조건에 맞는 배열을 얻을 수 있는 장점이 있습니다.

const arrDup = ['라이언', '어피치', '프로도', '콘', '라이언', '프로도'];
const arrUnique = arrDup.filter((val, idx) => {
  return arrDup.indexOf(val) === idx; //값이 처음나오는 배열 인덱스와 현재 인덱스가 같으면 포함
});
console.log(arrUnique); // ['라이언', '어피치', '프로도', '콘']

맵(Map)으로 배열 중복 제거

맵은 키-값 쌍으로 이루어진 요소를 가지는 객체입니다. 키는 중복될 수 없기 때문에 이 특성을 이용해 배열 요소를 키(Key)로 해서 맵에 데이터를 넣은 후, 객체 메서드인 keys()를 이용해 키 값만을 배열로 가져오는 식으로 중복 없는 배열을 생성합니다.

const arrDup = ['라이언', '어피치', '프로도', '콘', '라이언', '프로도'];
const objUnique = {}; // 중복없는 배열 요소만 담는 객체
arrDup.forEach(el => { 
  objUnique[el] = true; // {라이언: true, 어피치: true, 프로도: true, 콘: true}
});
const arrUnique = Object.keys(objUnique); // 객체 키만 모아서 배열로 반환
console.log(arrUnique); // ['라이언', '어피치', '프로도', '콘']

셋(Set)과 펼침 연산자로 배열 중복 제거

자바스크립트의 셋(Set) 객체는 맵(Map) 객체에서 값이 없고 키만 있는 것으로 이해하면 됩니다.

셋 객체 생성자는 배열을 인자로 받아서 중복이 없는 셋 객체를 반환하는 특징이 있습니다.

이 특징을 활용해서 중복이 없는 배열을 다시 만들 수 있습니다.

중복 있는 배열 -> 셋 -> 펼침 연산자로 펼침 -> 배열로 생성 과정을 거쳐 중복 없는 배열이 만들어집니다.

단 1행의 코드로 배열의 중복을 없앨 수 있기 때문에 단순히 배열의 중복을 없애는 것이 목적이면 이 방법이 가장 좋은 방법입니다.

const arrDup = ['라이언', '어피치', '프로도', '콘', '라이언', '프로도'];
const arrUnique = [...new Set(arrDup)];
console.log(arrUnique); // ['라이언', '어피치', '프로도', '콘']

필터(Filter)로 객체 배열의 중복 제거

객체를 배열 요소로 가지는 배열에서 중복된 객체 요소를 제거해서 중복이 없는 객체 배열을 생성할 수 있습니다.

앞서 사용했던 배열의 필터 메서드를 이용한 중복 제거 방법을 사용합니다.

배열 요소인 객체의 동일성은 객체의 값이 모두 동일한 것을 같은 객체인 것으로 구분합니다.

앞에서의 필터를 이용한 중복제거와 다른 점은 객체의 값들이 일치하는 첫 번째 객체의 배열 인덱스를 찾는 메서드가 findIndex() 메서드입니다.

indexOf() 메서드는 인자로 넘긴 값이 나오는 첫 번째 인덱스를 바로 반환할 수 있지만, 객체가 요소인 배열에서는 객체의 내부 값을 비교해야 하기 때문에 비교 함수 정의가 가능한 findIndex()의 인자로 객체의 값(들)을 비교하는 비교 함수를 넘겨서 첫 번째 값이 일치하는 객체의 배열 인덱스를 가져와야 합니다.

const arrDup = [{name:'라이언',company:'kakao'}, {name:'브라운',company:'naver'}, {name:'프로도',company:'kakao'}, {name:'라이언',company:'kakao'}, {name:'펭수',company:'ebs'}];
const arrUnique = arrDup.filter((character, idx, arr)=>{
    return arr.findIndex((item) => item.name === character.name && item.company === character.company) === idx
});
console.log(arrUnique);  // [{name:'라이언',company:'kakao'}, {name:'브라운',company:'naver'}, {name:'프로도',company:'kakao'}, {name:'펭수',company:'ebs'}]

맵(Map)으로 객체 배열의 중복 제거

객체를 배열 요소로 가지는 배열에서 중복된 객체 요소를 제거해서 중복이 없는 객체 배열을 생성할 수 있습니다.

앞서 사용했던 맵을 이용한 중복 제거 방법을 사용합니다.

배열 요소인 객체의 동일성은 객체의 값이 모두 동일한 것을 같은 객체인 것으로 구분합니다.

맵(Map), 또는 셋(Set)에 객체 배열을 문자열로 변환해서 넣는 방법에 대한 이해는 다음 글을 먼저 보면 도움이 됩니다.

> 자바스크립트 배열 요소의 중복 체크

const arrDup = [{name:'라이언',company:'kakao'}, {name:'브라운',company:'naver'}, {name:'프로도',company:'kakao'}, {name:'라이언',company:'kakao'}, {name:'펭수',company:'ebs'}];
const map = new Map(); // 맵
for(const character of arrDup){
    map.set(JSON.stringify(character), character); // name, company가 모두 같은 객체 요소는 제외한 맵 생성
}
const arrUnique = [...map.values()];
console.log(arrUnique);  // [{name:'라이언',company:'kakao'}, {name:'브라운',company:'naver'}, {name:'프로도',company:'kakao'}, {name:'펭수',company:'ebs'}]

맵에 항목을 추가하는 키(Key)는 배열 요소인 객체를 문자열화(JSON.stringify)해서 객체의 키와 값이 모두 같으면 같은 키가 되도록 하는 방식을 사용합니다.

맵의 값에는 배열의 객체 그대로를 저장해서 나중에 map.values() 메서드로 객체들만 빠르게 가져와서 배열로 만들 수 있도록 합니다.