JavaScript 배열의 중복 제거, 2차원 배열의 중복 제거

Jinny·2022년 3월 20일
2

우선 1차원 배열에서의 중복 제거 방법을 알아보자.

1. set

set은 ES6에서 등장한 새로운 data object이다. set내의 값은 유일하기 때문에 중복값이 존재하는 array를 넣게 되면 중복되는 값이 사라진다. ⇒ 가장 성능이 좋음(빠르다)

let arr = [1, 1, 2, 3, 4];
let uniqueSet = new Set(arr);
let uniqueArr = [...new Set(arr)]; // ... : 스프레드 연산자
console.log(uniqueArr);

//result : 
//Set(4) { 1, 2, 3, 4 }
//[1, 2, 3, 4]

2. filter

  • filter : 배열의 각 원소들을 콜백함수로 검사하여 true를 반환하는 요소들만 모아 배열로 리턴
  • indexOf : 배열에서 지정된 요소를 찾을 수 있는 첫 번째 인덱스를 반환, 존재하지 않으면 -1반환
let arr = [1, 1, 2, 3, 4];
let uniqueArr = arr.filter((element, index)=>{
	//element : 현재 순회중인 요소
  //index : 현재 순회중인 요소의 인덱스
	return arr.indexOf(element) === index;
});
console.log(uniqueArr);

//result : [1, 2, 3, 4]

3. forEach

let arr = [1, 1, 2, 3, 4];
let uniqueArr = [];
arr.forEach((element) => {
//배열 전체를 순회하면서 uniqueArr에 현재 순회중인 element가 존재하지 않는다면 push
	if(!uniqueArr.includes(element)){
		uniquArr.push(element);
	}
});
console.log(uniqueArr);

//result : [1, 2, 3, 4]

2차원 배열 중복 제거

위와 같이 1차원 배열에서의 중복 제거 방법을 보고 2차원 배열 중복 제거 시, 위와 같이 set 방식을 사용해봤는데 안된다!

let arr = [
  [1, 1],
  [1, 1],
  [1, 2],
  [1, 3],
];
let uniqueArr = new Set(arr);
console.log(uniqueArr);
// result = Set(4) { [ 1, 1 ], [ 1, 1 ], [ 1, 2 ], [ 1, 3 ] }

그래서 아래와 같은 방식을 사용했음
우선 indexOf와 findIndex의 차이를 알아보자

🌞 indexOf
: 지정된 요소와 일치하는 첫번째 인덱스를 반환

// 2차원 배열에서는 첫번째 인덱스를 반환안하고 해당 요소의 인덱스를 반환함
let locations = [
  [126, 34],
  [126, 34],
  [126, 35],
  [127, 34],
];
let uniqueArr = locations.filter((element, index) => {
  console.log(locations.indexOf(element));
  return locations.indexOf(element) === index;
});
console.log(uniqueArr);

//result : 
//0
//1
//2
//3
//[ [ 126, 34 ], [ 126, 34 ], [ 126, 35 ], [ 127, 34 ] ]

🌞 findIndex
: 주어진 판별함수를 만족하는 배열의 첫 번째 요소에 대한 인덱스를 반환
indexOf와 달리 함수를 통해 검사함 ⇒ 2차원 배열의 0,1번 요소 각각을 비교하는 판별함수를 사용함

//경위도 좌표가 담긴 2차원 배열
let locations = [
  [126, 34],
  [126, 34],
  [126, 35],
  [127, 34],
];
let uniqueArr = locations.filter((element, index) => {
  return (
		//1차원 배열에서는 indexOf를 사용했지만 다차원 배열에서는 안먹힘
    locations.findIndex(
      (item) => item[0] === element[0] && item[1] === element[1]
    ) === index
  );
});
console.log(uniqueArr);
//result : [ [ 126, 34 ], [ 126, 35 ], [ 127, 34 ] ]

💣그런데...!

대량의 데이터를 위의 방식으로 중복 제거를 하니까, 너무 오랜 시간이 소요되는 것...

뭐지뭐지 다른 방법을 찾다가 요기서 찾은 방법을 사용해보니까 훨씬 빠르게 동작했다😆

//최종 변경 코드
let locations = [
  [126, 34],
  [126, 34],
  [126, 35],
  [127, 34],
];

function removeDup(arr) {
  return [...new Set(arr.join("|").split("|"))]
    .map((v) => v.split(","))
    .map((v) => v.map((a) => +a));
}

let uniqueArr = removeDup(locations);
console.log(uniqueArr);

와 근데 왤케 어려워...ㅠㅠ

다차원 배열은 set 형태로 만들어봤자, 그대로니까 요걸 문자열 형태의 1차원 배열로 만든 다음에 set으로 만들어서 중복을 제거하고 다시 2차원 배열의 형태로 돌리는 방식인데,

하나씩 뜯어보자

🔎 join, split

- join : 배열의 모든 요소를 연결해 하나의 문자열로 만든다.
console.log(locations.join("|")); // 126,34|126,34|126,35|127,34

- split : String 객체를 지정한 구분자를 이용해 여러개의 문자열로 나눈다.
console.log(location.join("|").split("|")); //[ '126,34', '126,34', '126,35', '127,34' ]
자자 그럼 이제 set을 사용해서 중복 제거가 가능하겠즁~!

console.log([...new Set(location.join("|").split("|"))]); 
//[ '126,34', '126,35', '127,34' ]

🔎 map

: 배열 내의 모든 요소에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열로 반환

let unique = [...new Set(locations.join("|").split("|"))];
console.log(unique.map((v) => v.split(",")));
// [ [ '126', '34' ], [ '126', '35' ], [ '127', '34' ] ]

🔎 산술 연산자(Arithmetic Operators)

: mdn 이건 ㄹㅇ 첨보는거다... 🧐

* Unaray plus(+) 
+"3" returns 3, +true returns 1

v.map((a) => +a) 
이게 대체 뭔뜻인가 했더니 문자열을 숫자로 바꿔주는 것이였다....
단항연산자 : 피연산자가 숫자가 아니라면 숫자 형태로 바꾸는 기능을 한다.
mdn에서는 해당 연산자가 무언가를 숫자로 변경하는 가장 빠른 방법이라고도 적혀있다. 
* unary plus is the fastest and preferred way of converting something into a number

let uniqueArr = [
  ["126", "34"],
  ["126", "35"],
  ["127", "34"],
];
console.log(uniqueArr.map((v) => v.map((a) => +a)));
v는 ["126", "34"]와 같은 요소 하나하나
a는 그안에 있는 요소에 접근하는 것으로 "126"과 같은 문자열 요소들을 숫자로 바꿔준다.
// [ [ 126, 34 ], [ 126, 35 ], [ 127, 34 ] ]

틀린 부분이 있거나, 더 좋은 방법이 있다면 알려주세용~!!

참고한 사이트 출처

profile
조금씩 매일 성장해나가고 싶은 병아리 개발자입니다:)