front-end/Javascript

집합(Set)과 맵(Map)

hello${name} 2022. 5. 23. 17:03

자바스크립트 - 집합(Set)과 맵(Map)

 

 

본 글은 아래 사이트에 있는 내용을 한글로 번역해서 정리한 것입니다.

 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

 

Set - JavaScript | MDN

The Set object lets you store unique values of any type, whether primitive values or object references.

developer.mozilla.org

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

 

Map - JavaScript | MDN

The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.

developer.mozilla.org

 

 

 

 

1. 집합(Set)

 

 

  • Set 이란?

값들의 집합. 여기서 값은 원시 값(primitive values)나 객체(object references) 모두 될 수 있다.

Set과 Array의 가장 큰 차이점은 Set의 경우 Set 내 중복되는 값이 존재하지 않는다는 것이다.

 

 

- 값이 같은 지 판별하는 기준: sameValueZero

다음의 경우 같은 값이다.

- 둘 다 undefined
- 둘 다 null

- 둘 다 true 거나, 둘 다 false
- 같은 길이를 갖고 있으며 모든 characters가 같은 순서로 배열되어 있는 strings.
- 같은 객체 (여기서 같은 객체란, 메모리 내 같은 곳을 참조하고 있어야 함)
- 둘 다 number이며,
   - 둘 다 NaN

   - +0과 -0은 ECMAScript 2015로 오면서 같다고 판별하나, internet explorer에서는 다르다고 판별하니 주의

Set과 Map의 key, Array의 includes, String의 includes에 모두 적용되는 규칙이다.

 

 

- Performance

  특정 값이 있는지 판별하는 method인 has가 있다. 

  Set와 Array의 길이가 같아도(Set의 size와 Array의 length), Set의 has가 Array의 includes보다 빠르다고 한다.

 

 

- 프로퍼티(Properties)

  Set.prototype.size

  Set object 내의 값들의 개수를 반환한다.

 

 

- 메서드(Methods)

  ◇ Set.prototype.add(value)

        값 추가하기. 추가된 set object를 반환하며, 기존 set이 바뀐다.

  ◇ Set.prototype.clear()

        Set의 모든 값을 지운다. 아무것도 반환하지 않는다(undefined).

  ◇ Set.prototype.delete(value)

        Set 내 value를 지운다. 지우기에 성공했으면 (value가 set 내에 있으면) true, 실패했으면 (value가 set 내에 없으면) false를 반환한다

        * delete array[position] 과 비교하자면, array에서의 delete는 해당 자리의 값을 지우되 자리는 남겨놓는다. 즉 delete 후 해당 자리의 값이 undefined가 되는 것. Set의 delete는 그 값을 말끔하게 삭제한다!

  ◇ Set.prototype.has(value)

        Set 내 value가 있으면 true, 없으면 false를 반환한다

 

 

- Iteration methods

  ◇ Set.prototype[@@iterator]()

       값을 추가한 순서대로 iterate 한다. 

       사용법 예시) 

for (let item of mySet1) console.log(item)

 

 

  ◇ Set.prototype.values(), Set.prototype.keys()

       값을 추가한 순서대로 iterate 한다.

       Set에선 value와 key가 서로 같다. 

       사용법 예시) 

for (let item of mySet1.keys()) console.log(item)

  ◇ Set.prototype.entries()

       값을 추가한 순서대로 iterate 한다.

       Set에선 value와 key가 서로 같다. 

       사용법 예시) 

for (let [key, value] of mySet1.entries()) console.log(key)

  ◇ Set.prototype.forEach(callbackFn)

       Set 내 값을 callbackFn에 인수로 넘겨 callbackFn을 실행한다. 순서는 마찬가지로 추가된 순서대로. 

 

 

- Set을 Array로 변환하기

  1) Array.from 

  var myArr = Array.from(mySet);

  2) spread operator

  var myArr = [...mySet];

 

 

- Array를 Set으로 변환하기

  var mySet = new Set(myArr);

 


 

 

 

 

2. 맵(Map)

 

 

  • Map 이란?

키-값 쌍들(key-value pairs)의 집합. 값이 추가된 순서대로 저장된다. 여기서 원시 값(primitive values)과 객체(object references) 모두 키-값으로 사용될 수 있다.

 

- Map에서 key가 같은지 여부는 위 set에서 설명한 sameValueZero 알고리즘으로 판별한다.

 

- Object와 Map의 차이점

  1) Object의 key로는 string 또는 symbol만 가능하지만, map의 키로는 원시 값/객체 모두 가능하다.
  2) Map에서의 key는 삽입된 순서대로 정렬되어 있으며, iterate 할 시 해당 순서를 따른다.
       반면 object의 순서는... 다소 복잡하다. 현재로선 object의 key도 정렬되어 있다고 하나(?), object내 key 순서에 의존하는 것은 좋지 않다고 한다.
  3) Map은 size property로 그 개수를 쉽게 얻을 수 있지만, object에는 그런 property가 없다.
  4) Map은 iterable하다. 반면 Object는 javascript의 for ... of 문을 통한 직접적인 iterate가 불가하다. *Object.keys 또는 Object.entries로 가능은 하다고 한다...
  5) Performance: key-value 쌍으로 다뤄야 할 데이터의 경우 map의 performance가 더 좋다.
  6) Object은 JSON.stringify()와 JSON.parse()를 지원한다(native support. Map에는 이러한 native support는 없다고 나와있다.)
  7) Object에는 default key가 있으나, map에는 없다.

 

- 값 추가하기: Map.set(key, value)

  * 다음과 같이 object properties 설정하는 것처럼 할 수는 있지만, 혼란을 불러일으킬 수 있다!!

const wrongMap = new Map()
wrongMap['bla'] = 'blaa'
wrongMap['bla2'] = 'blaaa2'

console.log(wrongMap)  // Map { bla: 'blaa', bla2: 'blaaa2' }
wrongMap.has('bla')    // false
wrongMap.delete('bla') // false
console.log(wrongMap)  // Map { bla: 'blaa', bla2: 'blaaa2' }

  has로 key가 있냐고 물어볼 시 없다고 하고... delete로 key의 값을 삭제하려고 해도 실패한다.

  Map을 출력해보면 key-value 쌍이 들어있는데도 말이다.

 

  따라서 아래와 같이 set(key, value)로 값을 추가해줘야 한다.

const contacts = new Map()
contacts.set('Jessie', {phone: "213-555-1234", address: "123 N 1st Ave"})
contacts.has('Jessie') // true

 

- 프로퍼티(Properties)

  Map.prototype.size

  Map object 내의 key-value 쌍의 개수를 반환한다.

 

 

- 메서드(Methods)

  ◇ Map.prototype.set(key, value)

        값 추가하기. 추가된 map object를 반환하며, 기존 map이 바뀐다.

  ◇ Map.prototype.clear()

        Map의 모든 값을 지운다. 아무것도 반환하지 않는다(undefined).

  ◇ Map.prototype.delete(key)

        Map 내 key-value 쌍을 지운다. 지우기에 성공했으면 (key가 map 내에 있으면) true, 실패했으면 (key가 map 내에 없으면) false를 반환한다

  ◇ Map.prototype.has(key)

        Map 내 key가 있으면 true, 없으면 false를 반환한다

  ◇ Map.prototype.get(key)

        Map 내 key의 value를 반환한다. 해당 key가 map 내에 없으면 undefined를 반환한다.

 

 

- Iteration methods

  ◇ Map.prototype[@@iterator]()

       [key, value] 배열을 지닌 iterator object를 반환한다.

       사용법 예시) 

for (const [key, value] of myMap) {
  console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one

 

그 외... Set과 유사하므로 자세한 설명은 생략

 

◇ Map.prototype.keys()

◇ Map.prototype.values()

◇ Map.prototype.enteries()

 

◇ Map.prototype.forEach(callbackFn)

       사용법 예시) 

myMap.forEach(function(value, key) {
  console.log(key + ' = ' + value)
})
// 0 = zero
// 1 = one

 

- Map clone 하기

const first = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
])

 

- Map과 array merge 하기

const merged = new Map([...first, ...second, [1, 'eins']])