JavaScript로 개발하다 보면 객체 배열에서 특정 속성 값이 중복되는 항목을 제거해야 하는 경우가 자주 발생합니다. 이번 글에서는 name 속성을 기준으로 중복된 객체를 배열에서 삭제하는 방법을 알아보겠습니다.
문제 상황
다음과 같은 객체 배열이 있다고 가정해 봅시다.
const arr = [{name: "Jack", age: "14"},{name: "bob", age: "14"}, {name: "sue", age: "21"}, {name: "Jill", age: "16"}, {name: "Jack", age: "21"}];여기서 우리가 작성해야 할 함수는 name 속성 값이 중복되는 모든 객체를 제거하는 것입니다. 즉, 처음 등장한 name만 남기고 이후에 다시 나타나는 동일한 name을 가진 객체는 삭제해야 합니다.
따라서 위 배열에 함수를 적용하면 다음과 같은 결과가 나와야 합니다.
const arr = [{name: "Jack", age: "14"},{name: "bob", age: "14"}, {name: "sue", age: "21"}, {name: "Jill", age: "16"}];해결 방법: 등장 여부 추적 방식
핵심 아이디어는 이미 등장한 name 값을 별도의 객체에 기록해 두고, 반복문을 돌면서 이미 등장한 적이 있는 name을 가진 요소는 splice() 메서드로 제거하는 것입니다.
const arr = [
{name: "Jack", age: "14"},
{name: "bob", age: "14"},
{name: "sue", age: "21"},
{name: "Jill", age: "16"},
{name: "Jack", age: "21"}
];
const removeDuplicate = arr => {
const appeared = {};
for(let i = 0; i < arr.length; ){
if(!appeared.hasOwnProperty(arr[i].name)){
appeared[arr[i].name] = 1;
i++;
continue;
};
arr.splice(i, 1);
};
};
removeDuplicate(arr);
console.log(arr);코드 설명
appeared: 지금까지 등장한 name 값을 키로 저장하는 객체입니다.hasOwnProperty(): 현재 순회 중인 객체의 name이appeared에 존재하지 않으면 처음 등장한 것이므로 기록하고 인덱스를 증가시킵니다.arr.splice(i, 1): 이미 등장한 name이라면 해당 위치의 요소를 제거합니다. 이때 인덱스를 증가시키지 않는 점에 주목하세요. splice로 요소가 제거되면 뒤의 요소들이 앞으로 당겨지기 때문입니다.
실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 출력이 나타납니다.
[
{ name: 'Jack', age: '14' },
{ name: 'bob', age: '14' },
{ name: 'sue', age: '21' },
{ name: 'Jill', age: '16' }
]두 번째로 등장한 {name: "Jack", age: "21"} 객체가 성공적으로 제거되고, 첫 번째로 등장한 Jack만 배열에 남아 있는 것을 확인할 수 있습니다.
참고: Set을 활용한 더 간결한 방법
ES6 이상 환경이라면 Set과 filter()를 조합해 더 간결하게 작성할 수도 있습니다.
const seen = new Set();
const uniqueArr = arr.filter(item => {
if(seen.has(item.name)) return false;
seen.add(item.name);
return true;
});이 방식은 원본 배열을 변경하지 않고 새로운 배열을 반환하므로, 불변성(immuability)을 유지하고 싶은 경우에 유용합니다.