자바스크립트 배열에서 중복을 제거하는 방법은 여러가지가 있지만 일반적으로는 Set 객체를 활용하면 편리하게 중복을 제거할 수 있다.
2024.10.01 - [기타/코딩테스트] - (JS) Set [Programmers - 신고 결과 받기]
하지만 배열 내에 참조 타입이 들어있으면 Set으로 중복 제거가 되지 않는다. 내용물이 같더라도 메모리 상에 서로 다른 데이터로 존재하며 그 위치를 참조하여 사용하기때문에 Set 객체에서 중복을 검사할때는 참조값이 달라 중복으로 처리되지 않는다.
참조 타입이 포함되어있는 배열에서 중복을 제거할때는 아래와 같은 방법을 사용할 수 있다.
1. JSON.stringify 활용
배열내에 있는 모든 항목을 문자열로 변환하여 참조 값이 아닌 실제 데이터를 직접 비교하는 방법이다.
const arr = [
{ name: "kim", age: 30 },
{ name: "kim", age: 40 },
{ name: "kim", age: 30 },
{ name: "park", age: 35 }
];
const result = Array.from(new Set(arr.map(item => JSON.stringify(item))))
.map(item => JSON.parse(item));
console.log(result);
// [{ name: "kim", age: 30 }, { name: "kim", age: 40 }, { name: "park", age: 35 }]
배열내에 있는 모든 항목을 JSON 문자열로 변환하여 Set 객체로 중복을 제거한뒤 JSON.parse로 형식을 되돌린다. 이 방식을 활용하면 배열 항목으로 문자열만 들어있는 것과 같은 상황이므로 중복을 제대로 제거할 수 있다.
하지만 이 방식은 객체 혹은 배열내에 함수가 포함되어 있을 경우 사용할 수 없다. JSON.stringify는 함수를 직렬화하지 않기 때문이다. 함수가 포함된 배열에서 이 방식을 사용하면 JSON 표준에서 지원하지 않는 함수는 무시되어 빈 값이 되어버린다. 즉, 값 자체가 사라져 버린다.
const arr = [
{ a: 1, b: () => "hello" },
{ a: 1, b: () => "hello" },
{ a: 2, b: () => "world" }
];
const result = Array.from(new Set(arr.map(item => JSON.stringify(item))))
.map(item => JSON.parse(item));
console.log(result);
// [{ "a": 1 }, { "a": 2 }]
JSON에서 지원되지 않는 함수가 제거되었다. 함수의 중복을 제거하려면 복잡한 로직이 필요할 수 있지만 filter를 활용하면 제한적인 조건에서 중복을 쉽게 제거할 수 있다.
2. filter 활용
배열내에 특정 항목을 지정하여 비교한뒤 중복을 제거하는 방식이다.
const arr = [
{ name: "kim", age: 30 },
{ name: "kim", age: 40 },
{ name: "kim", age: 30 },
{ name: "park", age: 35 },
];
const test = arr.filter((val, idx, self) =>
idx === self.findIndex((t) => t.name === val.name));
console.log(test);
// [{ name: 'kim', age: 30 }, { name: 'park', age: 35 }]
배열내 객체에 있는 name이라는 key를 기준으로 잡고 비교하여 중복을 제거했다. 하지만 이 방식은 name이라는 key만을 기준으로 하므로 age의 차이를 구분할 수 없다. 이때에는 조건을 조금더 복잡하게 지정해야한다.
const arr = [
{ name: "kim", age: 30 },
{ name: "kim", age: 40 },
{ name: "kim", age: 30 },
{ name: "park", age: 35 },
];
const test = arr.filter((val, idx, self) =>
idx === self.findIndex((t) => t.name === val.name && t.age === val.age));
console.log(test);
// [{ name: 'kim', age: 30 },{ name: 'kim', age: 40 },{ name: 'park', age: 35 }]
배열속 객체의 name과 age를 둘다 비교하여 중복이 정상적으로 제거되었다.
filter를 활용하면 복잡한 객체나 배열, 서버로부터 받은 다량의 데이터 등을 여러가지 기준으로 비교하여 처리할 수 있어 활용성이 높다.
JSON.stringify 방식에서 문제가 된 함수 중복처리도 다른 key값을 기준으로 하여 정상적인 제거가 일부 환경에서 가능하다
const arr = [
{ a: 1, b: () => "hello" },
{ a: 1, b: () => "hello" },
{ a: 2, b: () => "world" }
];
const result = arr.filter((item, index, self) =>
index === self.findIndex((t) => t.a === item.a)
);
console.log(result);
// [{ a: 1, b: () => "hello" },{ a: 2, b: () => "world" }]
'Web > JS' 카테고리의 다른 글
Debounce와 Throttle을 통한 최적화 (0) | 2024.12.13 |
---|---|
구조 분해 할당 (0) | 2024.10.25 |
한국환경공단 대기오염 데이터 활용하기 (parseStringPromise, find, startsWith, padStart) (0) | 2024.10.13 |
화살표 함수의 특징 (0) | 2024.09.30 |
JS 모듈을 불러오는 require와 import (0) | 2024.05.20 |