Array of Object에서 중복 값을 제거하는 몇 가지 방법

llama·2022년 10월 6일
0

JavaScript

목록 보기
11/11
post-thumbnail

1. new Map() & new Set

key가 중복될 수 없는것을 이용한 방법이다.

💡 Map의 key type은 어느것도 될 수 있고, 순서를 보존한다.

간단한 설명

  1. Array.map()을 이용하여 Arr of Arr로 만드는데, 반환할 배열의 첫번째 요소에 비교할 값을 넣고, 두번째 요소에 해당 obj요소 자체를 넣어준다.
    • 첫번째 요소는 Map의 key로 들어갈 예정이다.
    • 두번째 요소는 Map의 value로 들어갈 예정이다.
  2. new Map(Arr of Arr)로 맵 객체를 만든다.
    • 동일한 key가 있다면 제거된다.
  3. 중복값이 제거됐다면 values()를 이용해 obj만 뽑아낸다.
  4. spread 연산자를 이용하여 배열에 복사하여 Map에서 Array of Object로 만들어준다.

Example

const uniqueObjArr = [ ...new Map(arr.map((obj) => [obj[key], obj])).values() ];

// 비슷한 방법으로 Set + JSON.stringify & parse를 이용하는것도 있다.
// 객체는 메모리 주소값이 달라 비교할 수 없기 때문에 문자열로 바꾸고 중복값 제거 후 다시 객체로 만드는 것이다.
// 🚨 단, 아래 방법은 모든 문자열을 비교하기 때문에 완벽히 일치하는 요소만 제거된다.
const uniqueObjArr = [ ...new Set(arr.map(JSON.stringify)) ].map(JSON.parse)

2. reduce() + findIndex()

Array.findIndex()에서 찾을 수 없다면 -1을 반환하는것을 이용한 것이다.

간단한 설명

  1. Array.reduce()를 이용하여 배열을 순회하는데, 초기값을 배열로 넣어준다.
  2. reduce의 첫번째 인자인 누산기에 findIndex를 이용하여 중복값 index를 찾아낸다.
    • 누산기에 담긴 값과, 현재 순회하는 값을 비교하고 만약 존재한다면 중복값인것이다.
  3. 중복값을 제거하는 것이기 때문에 2번에서 찾은 index가 -1일 경우에만 누산기에 더하고 누산기를 반환한다.
    • 새로운 값만 누산기에 더하고, 중복된 값은 넣지 않는 것이다.

Example

const uniqueObjArr = arr.reduce((acc, curr) => {
	const idx = acc.findIndex((obj) => obj[key] === curr[key]);
    if (idx === -1) acc.push(curr);
  	return acc;
}, []);

3. filter() + findIndex()

배열을 순회하며 현재 순회중인 index와 findIndex에서 찾은 index를 비교하여 첫번째로 찾아낸 item만 filter하여 중복값을 제거하는 것이다.

간단한 설명

  1. Array.filter()를 이용하여 배열을 순회하는데 elem, idx 두 인자를 받는다.
  2. 1번과 같은 Array에 findIndex()를 이용하여 filter에서 현재 순회중인 값과 비교하여 index를 찾아낸다.
    • 1번에서 세번째 인자로 filter를 도는 배열을 받아서 해당 배열을 순회돌아도 된다.
    • findIndex()가 처음 발견된 index를 반환하고 멈추는 것을 이용한 것이다.
  3. 현재 순회중인 요소의 index와 2번에서 찾은 index가 동일하다면 처음 발견된 요소이기 때문에 true를 반환하여 필터를 한다.

Example

const uniqueObjArr = arr.filter((obj, idx) => {
	const isFirstFindIdx = arr.findIndex((obj2) => obj2[key] === obj[key]);
	return isFirstFindIdx === idx;
});

📌 한 줄 회고

코드에 완벽한 정답은 없는것 같다. (성능은 장담 못한다🤪)

profile
요리사에서 프론트엔드 개발자를 준비하는중 입니다.

0개의 댓글