project/miniCode

JSON 어레이안 객체 특정프로퍼티 중복제거하기.

부엉이사장 2023. 5. 10. 17:46

# 실제 개발을 하면서..

여러 데이터들을 백단과 통신하면서 이런 데이터 구조를 많이 봤을것이다.

const userInfo = [
  { idx: 1, id: "helloman" },
  { idx: 2, id: "byeman" },
  { idx: 3, id: "sexman" },
  { idx: 4, id: "niceman" },
];

보통 db쪽에서 받은 데이터들을 JSON형식으로 받아오면 이런 데이터를 가져오게된다.

이런 '어레이안에있는 객체데이터들'을 반복문을 돌려서 사용해보자.

아래 포스팅에서 어레이와 객체를 반복문에 돌리는 방법들을 소개해봤다.

https://jacobowl.tistory.com/163

 

객체, 배열 반복문의 종류 / 어레이 순환 프로토타입 메서드

const arr = ["가", "나", "다"]; const obj = { key1: "value1", key2: "value2", key3: "value3" }; 이렇게 어레이와 오브젝트를 하나씩 만들었다. 이걸 반복문을 사용해서 처리를 해보자. ## for in 반복문 (배열 ok, 객체 o

jacobowl.tistory.com

 

 

 

## 대상 어레이

const userInfo = [
  { idx: 1, id: "helloman" },
  { idx: 2, id: "byeman" },
  { idx: 1, id: "sexman" },
  { idx: 3, id: "niceman" },
];

여기서 idx가 중복된 세번째 객체 sexman유저를 삭제하도록 하겠다. 

 

# filter 메서드

const uniqueUserInfo = userInfo.filter((info, index) => {
  return index === userInfo.findIndex((t) => t.idx === info.idx);
});

console.log(uniqueUserInfo);

가장 대중적으로 사용하는 방법임

- 설명 :

filter는 콜백함수에서 리턴하는 값의 조건이 true일때 그 값을 배열에 담아서 뱉어준다.

저위에서 조건은 userInfo 어레이의 인덱스가 userInfo의 findIndex랑 일치할경우 그 값을 새로운 어레이에 담아준다.

findIndex메서드는 객체의 프로토타입 메서드인데, 얘도 어레이안에 객체들을 하나씩 순회하면서 조건에 맞는 인덱스를 반환한다. find랑 다른점은 find는 값을 반환한다는것이구, findIndex는 인덱스값을 반환한다.

순회하면서 idx:1, id : sexman인 객체를 순회할때는

filter메서드에서 index가 2이고 filter메서드에서 현재순회중인 sexman유저의 idx는 1이다.

findIndex순회에서 첫번째 helloman유저 객체 차례때 idx가 1이라서 조건에 맞는데 findIndex메서드는 현재 순회중인 배열의 인덱스만을 반환한다. 그래서 userInfo.findIndex~가 반환하는건 0이다.

filter메서드의 index는 2, findIndex메서드의 값은 0이라서 조건에 부합하지 않기때문에 findIndex메서드는 순회를 끝내버려서 return값이 false가 되버린다.

 

설명이 ㅈ같이 복잡한데 그냥 직접 회로한번 그려보세용..

 

 

# map, Set

const uniqueUserInfo = [...new Set(userInfo.map((info) => info.idx))].map(
  (idx) => {
    return userInfo.find((info) => info.idx === idx);
  }
);

얘는 데이터가 클 경우 메모리를 많이 낭비할 수 있음.

- 설명 :

먼저 생성자 Set으로 중복이 제거된 어레이를 만든다. 객체는 모두 다른 메모리를 참조하므로 값이 똑같이 생겼더라도 다른 객체이기때문에 그냥 set에 담는다고 중복이 제거되지는 않는다.

암튼 Set에 담는것은 각 객체의 idx값이다. [1,2,1,3]이라는 어레이를 set처리하는것이다.

Set은 중복을 제거했기때문에, [1,2,3]이라는 어레이를 밷을것이고 이걸 이터러블로 담는다.

여기에 또 map을 적용해서 각 1,2,3을 또 순회하는데 

리턴하는 조건이 userInfo어레이에서 각유저의 객체의 idx가 현재 idx값과 일치하는 경우 어레이로 담아 리턴한다.

idx==1의 조건에 부합하는건 helloman과 sexman인데, find메서드는 순서대로 순회하면서 helloman유저를 먼저 찾아내고 종료해버리니 뒤에있는 sexman까지 이터러블순회가 되지 않는다.

 

# forEach, some 메서드

const uniqueUserInfo = [];
userInfo.forEach((item) => {
  if (!uniqueUserInfo.some((uniqueItem) => uniqueItem.idx === item.idx)) {
    uniqueUserInfo.push(item);
  }
});

console.log(uniqueUserInfo);

귀찮아서 생략.. 걍방식은 하나씩 unique어레이에 담는건데

조건으로 순회하는 현재 객체의 idx와 unique에 담겨있는 객체들도 순회하면서 idx값 같은거있으면 안담는 방식인듯.

 

 

# reduce메서드

const uniqueUserInfo = userInfo.reduce((acc, curr) => {
  if (!acc.some((info) => info.idx === curr.idx)) {
    acc.push(curr);
  }
  return acc;
}, []);

unerInfo reduce로 순회하는데

불린조건이 some 메서드로 이전값 담은 어레이를 하나씩 순회하면서 이전까지 담은 user객체들의 idx와 reduce에서 도는 현재유저객체 idx같은거 하나도 없으면 push하는 방식인듯.

 

 

 

 

사실 저렇게 JSON으로 잘못된 어레이안 객체들을 받는건 안좋은방법이다.

저 유저정보들은 sql db에 담긴 정보들일텐데, idx를 프라이머리키로 등록을 해서 저렇게 idx가 같은 유저는 애초에 db에 처넣지 말아야한다..

최대한 db에 쿼리문 날릴때 조건을 정확히해서 자료들을 가져와야하고 프론트단에선 최소한으로 하는게 좋을것이다..

백단은 충실히합시다..

 

반면 예를들어 장바구니에 물건을 담는데 장바구니는 유저 로그인안해도 되는경우 많이 봤을거다.

이건 프론트단에서 처리된다는건데..

이미 어떤 상품객체가 장바구니 어레이에 담겨있는데, 이 상품번호가 중복된게 이미 있으면 수량만 +1로 한다던가 이런식으로 해야한다..

이건 프론트단에서 처리를 하기로했으니 오늘 포스팅한 배열안에 객체들 순회/ 중복제거방법을 익혀두면 유용하게 쓸 수 있을듯.