배열 비교하기

GI JUNG·2022년 11월 16일
3

javascript

목록 보기
4/12
post-thumbnail

programmers에 새로 올라온 문제(햄버거 만들기)를 javascript로 시간 복잡도 생각 안 하고 흐름대로 풀다가 배열을 비교하는 부분에서 오류가 났었다. 따라서 javascript는 python과 달리 배열을 비교하는 것이 다르구나!!해서 공부할 겸 정리할 겸 포스트를 올려본다.

일단, python과 js로 배열을 비교하는 것을 살펴보자!

🍀 compare array with python & javascript

arr1 = [1, 2, 3]
arr2 = [1, 2, 3]

print(arr1 == arr2)  // True
const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];

console.log(arr1 === arr2)   // false

js에서는 false가 나왔다. 혹시?? 하는 마음에 == operator를 사용해보았다.

const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];

console.log(arr1 == arr2)   // false

이것도 false가 나온다. python으로 알고리즘 풀이를 하던 나에게는 좀 이질감이 있었지만 한참 고민하다가 javascript에서 배열도 object로서 참조값으로 비교하는 것이 아닐까?라는 의문을 가지게 되었는데 찾아보니 결과적으로 맞추었다!!🥳

참조값으로 객체를 비교한다고??? 라는 의문이 든다면 아래 class예제를 보자


class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  printInfo() {
    console.log(`name: ${this.name}\tage: ${this.age}`);
  }
}

const tom = new Person("Tom", 22);
const tom1 = new Person("Tom", 22);

console.log(tom1 === tom1);   // false

tomtom1name, age가 같지만 tom과 tom1은 같지않다.
클래스를 공부해봤다면 같은 클래스(여기서 Person)로부터 만들어진 instance는 각각 고유한 객체로서 다른 주소값(참조값)을 가지기 때문이다.

📒 따라서 javascript는 Array class로 부터 array를 만듬으로 같은 요소를 가진 배열이라 해도 참조값이 달라 다른 배열이라고 판단한다.

🍀 Compare two arrays in js

여기서 저기서 찾아보고 혼자 생각해보고 취합한 결과 총 3가지방법을 모아봤다.
1, 2, 3은 javascript에서 string을 비교하는 원리를 이용한 것이다.

  1. use JSON.stringify()
  2. use toString method
  3. use for statement to compare two arrays

1️⃣ JSON.stringify

function isSame(arr1, arr2) {
  if (arr1.length !== arr2.length) {
    throw new Error("length is different!!");
  } else if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
    throw new Error("both of object should have array type!!");
  }

  return JSON.stringify(arr1) === JSON.stringify(arr2);
}

const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
const arr3 = [2, 3, 4];

console.log(isSame(arr1, arr2));   // true
console.log(isSame(arr1, arr3));   // false

2️⃣ toString

function isSame(arr1, arr2) {
  ...// // 👈 handle error can see above JSON.stringify code
  return arr1.toString() === arr2.toString();
}

const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
const arr3 = [2, 3, 4];

console.log(isSame(arr1, arr2));   // true
console.log(isSame(arr1, arr3));   // false

3️⃣ for statement

function isSame(arr1, arr2) {
  ...// // 👈 handle error can see above JSON.stringify code
  let result = true;
  
  for (let i = 0; i < arr1.length; i++) {
    if (arr1[i] !== arr2[i]) {
      result = false;
      break;
    }
  }

  return result;
}

const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
const arr3 = [2, 3, 4];

console.log(isSame(arr1, arr2));   // true
console.log(isSame(arr1, arr3));   // false

🤔 어느 것이 제일 빠를까?

이것은 어느 것을 쓰는게 제일 빠를까 생각이 들어서 코드를 짜보게 되었다. 현대는 메모리는 충분하여 메모리 효율보다는 시간 효율을 중시한다는 얘기를 얼핏 들었다. 여러방법을 알아도 빠르면서 나에게 맞는 방법을 찾고자 한 번 테스트 해 봤다.
for-stat, stringify, toString모두 O(n)의 시간 복잡도를 가지므로 거기서 거기라고 생각했지만, for 구문에 break(값을 비교하다가 중간에 틀리면 바로 루프를 중단하면 되므로)를 건다면 다른 것보다 훨씬 빠를 수 있다고 생각했다.

일단, 전체 코드는 아래와 같다.

test code


function isSuitable(arr1, arr2) {
  let result = true;

  if (arr1.length !== arr2.length) {
    result = false;
    throw new Error("length is different!!");
  } else if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
    result = false;
    throw new Error("both of object should have array type!!");
  }

  return result;
}

function isSameJSON(arr1, arr2) {
  if (isSuitable(arr1, arr2)) {
    return JSON.stringify(arr1) === JSON.stringify(arr2);
  }

  return console.error("unexpected error!!");
}

function isSameToString(arr1, arr2) {
  if (isSuitable(arr1, arr2)) {
    return arr1.toString() === arr2.toString();
  }

  return console.error("unexpected error!!");
}

function isSameFor(arr1, arr2) {
  let result = true;

  if (isSuitable(arr1, arr2)) {
    for (let i = 0; i < arr1.length; i++) {
      if (arr1[i] !== arr2[i]) {
        result = false;
        break;
      }
    }

    return result;
  }

  return console.error("unexpected error!!");
}

function createArray(arrayLength, maxNumber) {
  const arr = [];
  for (let i = 0; i < arrayLength; i++) {
    arr.push(Math.floor(Math.random() * maxNumber));
  }

  return arr;
}


const LENGTH = 100000000;
const MAX_NUMBER = 4;
const arr1 = (arr2 = createArray(LENGTH, MAX_NUMBER));
const arr3 = createArray(LENGTH, MAX_NUMBER);

console.time("JSON.stringify");
isSameJSON(arr1, arr2);
isSameJSON(arr1, arr3);
console.timeEnd("JSON.stringify");

console.time("toString");
isSameToString(arr1, arr2);
isSameToString(arr1, arr3);
console.timeEnd("toString");

console.time("for same array");
isSameFor(arr1, arr2);
console.timeEnd("for same array");

console.time("for not same array");
isSameFor(arr1, arr3);
console.timeEnd("for not same array");

배열의 길이 1억으로 스스로 테스트를 해본 결과 for-stat > JSON.stringify > toString 순으로 빨랐다. 그냥 for-stat가 압도적으로 빨랐다... ㄷㄷ😳

🚀 마치며

테스트를 정확히 할 줄 몰라 정확하게 테스트를 한 지는 모르지만, 스스로 해 본 결과 for구문을 이용하는 것이 가장 빠름을 보았다. 사실상 toString, stringify를 쓰는 것이 덜 수고스럽지만 많은 데이터를 다룰 때는 for구문을 이용하고 데이터가 적다면 stringify를 이용하여 비교를 해야겠다. 문득 든 생각으로 스스로 테스트 코드??를 짰는데 값진 것을 얻어가는 느낌이라 기분이 좋다!!😁

참고

how does compare objects in javascript

profile
step by step

0개의 댓글