자바스크립트 - Array VS Set

유진·2021년 1월 18일
8
post-thumbnail

Array와 Set... 누가 더 짱쎈놈일까?

1. Set 객체

1) Set 기본

Set은 ES6부터 새롭게 도입된 자바스크립트 객체이다. 기본적으로는 값들의 집합이며, 순서를 가진다.

Set과 Array를 구별하는 Set의 가장 큰 특징은 중복된 값을 허용하지 않는다는 것이다.

Set에서의 값 비교
Set의 모든 값들은 고유하기 때문에, 새로운 값을 추가하거나 변경하면 값 비교가 이루어진다. 값 비교는 자바스크립트의 === 알고리즘과 동일하다.

let mySet = new Set(); // set 생성

mySet.add(1);           // Set [ 1 ]
mySet.add('hi');        // Set [ 1, 'hi' ]

const o = {a:1, b:2};
mySet.add(o); 
mySet.add({a:1, b:2}); // o 객체와 다른 객체로 취급되어 정상적으로 추가된다.

mySet.has(1); // true
mySet.has(o); // true

console.log(mySet.size);   // 5

mySet.delete(1); // Set ['hi']
mySet.has(1);    // false

2) Iterating Sets

const mySet = new Set(1, 'hi', {a:1, b:2}, {a:1, b:2});

/* for...of 사용 */
for (let item of mySet) console.log(item);
// 1, hi, {a:1, b:2}, {a:1, b:2}

for (let item of mySet.values()) console.log(item);
//mySet.values()와 mySet.keys()는 
//set의 모든 값을 포함한 새로운 Iterator 객체를 반환함

/* forEach 사용 */
mySet.forEach(function(val) {
    console.log(val);
});

3) Set과 Array 사이 변환

/* Set 객체를 Array로 변환 */
// Array.from 메서드 사용
var myArr = Array.from(mySet);

// rest parameter를 이용
var myArr2 = [...mySet];

/* Array를 Set 객체로 변환 */
var mySet2 = new Set(myArr2);

2. Array와 Set 성능 비교

ES6이 나온 이후로 다들 이런 생각을 한번쯤 했을 것이다. 그래서 Set 객체는 왜 만든건데?

왜냐면, (적어도 나한테 있어서) Set은 그냥 중복값을 넣을 수 없는 배열과 다를 바가 없이 느껴졌기 때문이다. 그리고 실제로도 그렇다.

그래서 스택오버플로에 검색해보니 누군가가 배열과 Set을 비교하기 위한 실험을 진행한 것을 발견했다. (Javascript Set vs. Array performance)

첫번째 답변을 간략히 요약하면 다음과 같다.


테스트는 요소가 약 10,000개 들어있는 작은 테스트와 100,000개 정도 들어가는 큰 테스트로 나누어 진행했다.

  • 요소 추가 테스트: array에 .push를 쓰는 것이 set에 .add를 쓰는 것보다 약 4배 빠르다. (요소를 얼마나 추가하는지는 상관 x)

  • Iterating과 요소 변경 테스트: for문으로 array를 iterate하는 것이 for...of로 set을 iterate하는 것보다 빨랐다. 심지어 작은 테스트에서는 두배 차이났지만, 큰 테스트에서는 4배 차이가 났다.

  • 요소 제거 테스트: 가장 흥미로운 부분! for문과 .splice를 이용해 array에서 요소를 제거하고, for...of.delete를 이용해 set에서 요소를 제거했다. 작은 테스트에서는 set이 array에 비해 세 배 정도 빨랐으나(2.6ms vs 7.1ms), 큰 테스트에서는 무려 23배 차이가 났다. (83.6ms vs 1955.1ms)

결론적으로, 요소를 제거할 때는 set으로 연산하는 것이 빠르고, 그 외에는 array가 더 빠르다.


3. Set은 왜 만들어졌나?

이 부분은... 사실 ECMAScript 공식 문서를 읽어봤는데 잘 모르겠고, 스택오버플로에 누군가가 써 둔 글(Javascript set vs array vs object definition)을 대신 옮겨두겠다.

왜 Set이 소개되었는가?(추측)
고유한 값들로 구성된 집합을 만들 필요가 가끔씩 생긴다. 값을 추가할 때마다 해당 값이 이미 있는지 확인하고 값을 추가하는 기존 방식은 매우 큰 오버헤드를 발생시킨다.
간단하게 진행한 실험에서, 10,000개의 요소를 가진 배열에 15개의 요소를 추가하는 데, 요소를 추가하기 전에 추가하려는 값이 배열에 들어있는지 확인해서 중복값은 스킵하는 과정을 추가했다. 이 실험은 74ms가 걸렸다. 그러나 동일 조건에서 set.add(value)를 했을 때는 고작 9ms 걸렸다.

단순히 중복값을 허용하지 않는 집합이 필요할 때도 좋을 것 같고, 중복값이 있는지 확인해야 할 때 Array에서 Set으로 바꾸고 중복값을 체크하는 방식도 유용할 것 같다.

-끝-

profile
제가 또 기가막힌 한 줌의 트러플 소금 같은 존재그등요

0개의 댓글