본문 바로가기
개발/자바스크립트

[자바스크립트] 배열 비교하는 3가지 방법 + 형님의 솔루션

by 핸디(Handy) 2020. 9. 27.

배열을 비교하는 방법

코딩을 하다 보면 필연적으로 값을 비교하는 경우가 있습니다.
이번 글에서는 그중에 배열을 비교하는 방법에 대해 논해보고자 합니다.

제가 이때까지 한 코딩을 생각해보니 위의 2가지 방법을 주로 썼습니다.

  1. 반복문을 이용해 값을 하나씩 읽어와 비교하는 방법
  2. Array.toString 를 이용하는 문자열로 바꿔 방법
  3. JSON.stringify 를 이용하여 문자열로 바꿔 방법

일반적으로 값을 하나씩 비교하는 것은 아래 2가지 방법보다 시간이 오래 걸릴 테니 2,3번 방법의 속도를 비교해보도록 하겠습니다.

== VS === 에 따른 이상한 배열 비교

일단 바꾸기 전에 잠깐 자바스크립트의 비교 문법에 대해 살펴보고 가겠습니다.

첫번째 :  == 비교이기 때문에 같은 타입이라 형변환없이 비교합니다. 그러다 보니 배열의 주소를 비교하니 false가 나옵니다.

두번째 : == 비교이나 서로 다른 타입이기 때문에 형변환이 일어납니다. 문자열로 변환되어 비교하기 때문에 true가 나옵니다.

세번째 : 두번째 방법과 동일합니다. 같은 문자열 비교이기 때문에 true가 나옵니다.

네번째 : === 비교는 형변환없이 하는 비교이긴 하지만 이미 string이 되었기 때문에 true 나옵니다.

다섯번째 : 배열의 값이 다르기 때문에 당연히 false 가 나옵니다.

Array.toString 방법 | 코드

a.toString()== b.toString()으로 array내부에 있는 값을 toString으로 만들고 비교했다.

var nStart = new Date().getTime();      //시작시간 체크(단위 ms)
var a = [1,2,3,4,5,6,7,8,9,10];
var b = [1,2,3,4,5,6,7,8,9,10];
for(let i = 0; i <10000000 ; i++){
    a.toString()== b.toString();
}
var nEnd =  new Date().getTime();      //종료시간 체크(단위 ms)

var nDiff = nEnd - nStart;  
console.log(nDiff)

JSON.stringify  방법 | 코드

var nStart = new Date().getTime();      //시작시간 체크(단위 ms)
var a = [1,2,3,4,5,6,7,8,9,10];
var b = [1,2,3,4,5,6,7,8,9,10];
for(let i = 0; i <10000000 ; i++){
    JSON.stringify(a)==JSON.stringify(b);
}
var nEnd =  new Date().getTime();      //종료시간 체크(단위 ms)

var nDiff = nEnd - nStart;  
console.log(nDiff)

Array.toString VS JSON.stringify | 비교표

  1회 2회 3회 4회 5회
toString( ) 6535 6458 6488 6402 6542
JSON.stringify( ) 4940 4837 4864 4989 4967

toString의 경우 6500ms, JSON.stringify는 4900ms를 보여줘서 속도면에서는  JSON.stringify이 더 빠르다는 것을 확인했습니다.


결론은 toString 인가?

속도는 빠르지만 일반적으로 배열을 toString으로 비교하겠다는 생각엔 심각한 오류가 있습니다.

위의 코드에서 볼 수 있듯이 배열 안에 여러 가지 타입이 있을 경우 원하는 대로 동작하지 않습니다.

다시 확인해보면 객체를 toString으로 타입변경을 하면 그냥 [object Object]가 나와버립니다. 이것은 자바스크립트의 프로토타입에 의한 것으로 보시다시피 toString으로는 한계가 있음을 확인했습니다.

var a = [1,2,3,4,5,6,7,8,9,{test:test}];
var b = [1,2,3,4,5,6,7,8,9,{test:test2}];

JSON.stringify(a)==JSON.stringify(b) // false
a.toString() == b.toString() // true <- Oops!!

따라서 그냥 편하게 사용하려면 JSON.stringify(a)===JSON.stringify(b) 를 쓰십시오.


Best practice | 하나씩 비교

이제 JSON.stringify로 비교하는 게 가장 적절한 방법이라는 결론을 얻었습니다. 근데 과연 이게 best practice인가에 대한 고민을 가지고 다시 구글링을 시작해보았습니다.

글로벌 개발자 형님들의 추천 픽은?

바로 하나씩 비교하는 방법입니다.

 

How to compare arrays in JavaScript?

I'd like to compare two arrays... ideally, efficiently. Nothing fancy, just true if they are identical, and false if not. Not surprisingly, the comparison operator doesn't seem to work. var a1 = [...

stackoverflow.com

JSON.stringify 는 직렬화가 가능한 배열에서만 사용 가능하며 배열 크기가 커질수록 직렬화 과정에서 시간을 잡아먹게 됩니다.

또한 코딩 스킬 중에 early return를 적용하라는 말처럼 반복문을 통해 하나씩 비교하면 

전체 배열을 순회하지 않고 다른 배열 인덱스에서 바로 다르다는 것을 확인할 수가 있습니다.

또한 배열 내용을 비교하기 전에 배열 크기부터 비교함으로 불필요한 비교를 제거하는 방법도 설명해주고 있으니 한번 쭉 읽어보시면 좋을 것 같습니다.


결론 : 정답은 없다

스택오버플로어에 나온 답변을 보듯이 배열의 비교하는 방법에 대한 주장이 모두 다릅니다.

사전에 배열에 확실히 string만 있다고 보장이 된다면 toString를 써도 된다는 답변도 있고, 배열을 비교하는 기준이 따라 답이 다르다는 답변도 있습니다.

결국 자바스크립트에 대한 이해를 바탕으로 "적절한 수준의 비교 알고리즘을 써야 한다"라고 생각하게 되었습니다.

그러니 그때그때 어떤 배열을 비교할 건지 고민하고 그때그때 비교 로직을 세워보도록 합시다.

댓글