[Javascript] Map and Set

Suyeon·2020년 8월 30일
3

Javascript

목록 보기
10/31

Map

  • Map은 key가 있는 데이터를 저장할 수 있다. (object와 유사해보이지만 map은 key에 다양한 자료형을 허용한다.)

✔️ Map vs Object

object와 map은 유사해보이는데.. 그렇다면 언제 어떤것을 써야할까?

  • Key: key값으로 primitive value을 써야할 때는 map을 사용 (number, object, boolean, NaN, etc)
  • Order: insertion order를 기억해야할 때는 map을 사용
  • Size: map에서는 쉽게 size를 얻을 수 있다. (Object에서는 Object.keys(obj).length로 접근가능)
// (1) key의 다양한 자료형
let map = new Map();

map.set('1', 'str1');   // string
map.set(1, 'num1');     // number

alert( map.get(1)   ); // 'num1'
alert( map.get('1') ); // 'str1'

// (2) key로 object 사용
let john = { name: "John" };
let visitsCountMap = new Map();
visitsCountMap.set(john, 123);

alert( visitsCountMap.get(john) ); // 123

Methods

  • new Map() – 맵을 만듬
  • map.set(key, value) – key를 이용해 value를 저장
  • map.get(key) – key에 해당하는 값을 반환함 (key가 존재하지 않으면 undefined를 반환)
  • map.has(key) – key가 존재하면 true, 존재하지 않으면 false를 반환.
  • map.delete(key) – key에 해당하는 값을 삭제
  • map.clear() – 맵 안의 모든 요소를 제거
  • map.size – 요소의 개수를 반환

Iteration

  • map.keys() – key를 모은 iterable object를 반환
  • map.values() – value을 모은 iterable object를 반환
  • map.entries() – [key, value]을 한 쌍으로 하는 iterable object를 반환
let recipeMap = new Map([
  ['cucumber', 500],
  ['tomatoes', 350],
  ['onion',    50]
]);

// map.keys()
for (let vegetable of recipeMap.keys()) {
  alert(vegetable); // cucumber, tomatoes, onion
}

// map.values()
for (let amount of recipeMap.values()) {
  alert(amount); // 500, 350, 50
}

// map.entries
for (let entry of recipeMap) { // recipeMap.entries()와 동일
  alert(entry); // cucumber,500 ...
}

// Map은 object와 다르게 property 순서를 기억함

Conversion

  • Object.entreis - object를 map으로 변환
  • Object.fromEntries - map을 object로 변환 (자료가 map에 저장되어있는데, third-party code에서 자료를 object로 넘겨받길 원할 때 이 방법을 사용할 수 있음)
// (1) Convert object to map
let obj = {
  name: "John",
  age: 30
};

let map = new Map(Object.entries(obj));
alert( map.get('name') ); // John

// (2) Convert map to object
let map = new Map();
map.set('banana', 1);
map.set('orange', 2);
map.set('meat', 4);

let obj = Object.fromEntries(map);
// obj = { banana: 1, orange: 2, meat: 4 }

alert(prices.orange); // 2

Set

  • Set은 중복을 허용하지 않는 값을 모아논 컬렉션이다. 셋에는 키가 없는 값이 저장된다.

Methods

  • new Set(iterable) – iterable object를 전달받으면(대개 배열을 전달받음) 그 안의 값을 복사해 set에 넣어줌.
  • set.add(value) – 값을 추가하고 set 자신을 반환.
  • set.delete(value) – 값을 제거함. 호출 시점에 set의 값이 있어서 제거에 성공하면 true, 아니면 false를 반환.
  • set.has(value) – set 내에 값이 존재하면 true, 아니면 false를 반환
  • set.clear() – set을 비움.
  • set.size – set에 몇 개의 값이 있는지 세어줌.
/*
방문자 방명록을 만든다고 가정해 봅시다. 한 방문자가 여러 번 방문해도 방문자를 
중복해서 기록하지 않겠다고 결정 내린 상황입니다. 즉, 한 방문자는 '단 한 번만 기록’되어야 합니다. 
이때 적합한 자료구조가 바로 셋입니다!
*/

let set = new Set();

let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };

// 어떤 고객(john, mary)은 여러 번 방문할 수 있습니다.
set.add(john);
set.add(pete);
set.add(mary);
set.add(john);
set.add(mary);

alert( set.size ); // 3
  • arr.find를 사용할 수도 있지만 set보다 성능면에서 떨어진다. (배열 내 요소전체를 뒤져 중복값을 찾기 때문). 따라서 중복값을 찾을 때에는 set이 최고!

Iteration

  • for..of / forEach
let set = new Set(["oranges", "apples", "bananas"]);

// (1) for..of
for (let value of set) alert(value);

// (2) forEach
set.forEach((value, valueAgain, set) => {
  alert(value);
})

WeakMap and WeakSet

자바스크립트 엔진은 reachable value를 메모리에 유지한다. 자료구조를 구성하는 요소도 자신이 속한 자료구조가 메모리에 남아있는 동안 대개 도달 가능한 값으로 취급되어 메모리에서 삭제되지 않습니다. 객체의 프로퍼티나 배열의 요소, 맵이나 셋을 구성하는 요소들이 이에 해당한다.

Reference 참고!

// (1) Array
let john = { name: "John" };
let array = [ john ];
john = null;

alert(JSON.stringify(array[0])); // 여전히 메모리에 남아있음(값을 얻는 것도 가능)

// (2)  Map
let john = { name: "John" };

let map = new Map();
map.set(john, "...");

john = null; 

alert(map.size); // 1, 여전히 메모리에 남아있음

WeakMap

  • WeakMap의 key로 사용된 object를 참조하는 것이 아무것도 없다면 해당 object는 메모리와 weakMap에서 자동으로 삭제된다.
  • Key는 반드시 object이여야 한다. (primitive X)
  • Iteration과 keys(), values(), entries() 메서드를 지원하지 않기 때문에 key나 value 전체를 얻는 게 불가능하다.
  • "추가 데이터"(additional data)를 저장할 때 유용함.
  • Chaching에 유용함.

Methods

  • weakMap.get(key)
  • weakMap.set(key, value)
  • weakMap.delete(key)
  • weakMap.has(key)

WeakSet

'위크’맵과 유사하게 '위크’셋도 부차적인 데이터를 저장할 때 사용할 수 있다. 다만, 위크셋엔 위크맵처럼 복잡한 데이터를 저장하지 않는다. 대신 "예"나 “아니오” 같은 간단한 답변을 얻는 용도로 사용된다. 물론 위크셋에 저장되는 값들은 객체이다.

Methods

  • weakSet.add(obj)
  • weakSet.has(obj)
  • weakSet.delete(obj)

Example

let visitedSet = new WeakSet();

let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };

visitedSet.add(john); 
visitedSet.add(pete); 
visitedSet.add(john); // John이 재방문

// visitedSet엔 두 명의 사용자가 저장될 겁니다.

// John의 방문 여부를 확인해보겠습니다.
alert(visitedSet.has(john)); // true

// Mary의 방문 여부를 확인해보겠습니다.
alert(visitedSet.has(mary)); // false

john = null;

// visitedSet에서 john을 나타내는 객체가 자동으로 삭제됩니다.
profile
Hello World.

0개의 댓글