완벽한 다음 행보는 없다.

[Javascript] Map과 Set 본문

Javascript

[Javascript] Map과 Set

We On Fire 2023. 9. 18. 10:07

Map

  • 맵은 키값 쌍을 저장하는 데이터 구조로 객체와 유사한 역할을 한다.
  • 순서를 보장하며 요소의 추가 및 삭제 시 순서가 유지된다. 객체는 순서 보장하지 않음.
  • 객체와 달리 다양한 자료형을 키로 사용할 수 있다. 객체는 문자열, 심볼만 가능.
  • Map은 이터러블하며 for, for-of, forEach를 통해 반복 가능하다. 반면 객체는 direct하게 iterate할 수 없음. 그래서 Object.keys, Object.entries, for..in 구문 사용하여야 함.

주요 메소드

  • 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 – 요소의 개수를 반환합니다.

값에 접근하는 방법

//객체의 경우
const object = {
	name : 'hi',
	age : 30,
	sex : 'male'
}
console.log(object.name); // 'hi'
console.log(object['name']; // 'hi'
console.log(object.get("sex"); // TypeError : object.get is not a function

//맵의 경우
const map = new Map();
map.set('name', 'Hi');
map.set('age', 30);
map.set(1, 'num1');
//아래와 같이 작성 가능
const map = new Map([['name', 'Hi'], ['age', 30], [1, 'num']])
const map = new Map().set('name', 'Hi').set('age', 30).set(1.'num');

console.log(map.get('name')); //"Hi"
console.log(map.get('age')); //30
console.log(map.get(1)); // 'num1'

map.delete('age')
for(const [key, value] of map) {
	console.log(`$(key): $(value)`);
) // name : Hi
	// 1 : num1

// 각 (키, 값) 쌍을 대상으로 함수를 실행
map.forEach( (value, key, map) => {
  alert(`${key}: ${value}`); // cucumber: 500 ...
});

맵의 요소에 반복 작업하기

  • map.keys() – 각 요소의 키를 모은 이터러블(iterable, 반복 가능한) 객체를 반환합니다.
  • map.values() – 각 요소의 값을 모은 이터러블 객체를 반환합니다.
  • map.entries() – 요소의 [키, 값]을 한 쌍으로 하는 이터러블 객체를 반환합니다. 이 이터러블 객체는 for..of반복문의 기초로 쓰입니다.
let recipeMap = new Map([
  ['cucumber', 500],
  ['tomatoes', 350],
  ['onion',    50]
]);

// 키(vegetable)를 대상으로 순회합니다.
for (let vegetable of recipeMap.keys()) {
  alert(vegetable); // cucumber, tomatoes, onion
}

// 값(amount)을 대상으로 순회합니다.
for (let amount of recipeMap.values()) {
  alert(amount); // 500, 350, 50
}

// [키, 값] 쌍을 대상으로 순회합니다.
for (let entry of recipeMap) { // recipeMap.entries()와 동일.
  alert(entry); // ['cucumber',500] ['tomatoes', 350] ['onion', 50] 
}
//키, 밸류 따로 접근하는 방식
for (let [key, value] of recipeMap) {
  alert(`${key} + ${value}`); // cucumber + 500, tomatoes + 350, ...
}

// forEach도 지원. 각 (키, 값) 쌍을 대상으로 함수를 실행
recipeMap.forEach((value, key, map) => {
  alert(`${key}: ${value}`); // cucumber: 500 ...
});

Set

  • Set은 중복을 허용하지 않은 값을 모아 놓은 컬렉션. 셋에 키가 없는 값이 저장됨. 일반 배열 리터럴과 비슷.

주요 메서드

  • new Set(iterable) – 셋을 만듭니다. 이터러블 객체를 전달받으면(대개 배열을 전달받음) 그 안의 값을 복사해 셋에 넣어줍니다.
  • set.add(value) – 값을 추가하고 셋 자신을 반환합니다.
  • set.delete(value) – 값을 제거합니다. 호출 시점에 셋 내에 값이 있어서 제거에 성공하면 true, 아니면 false를 반환합니다.
  • set.has(value) – 셋 내에 값이 존재하면 true, 아니면 false를 반환합니다.
  • set.clear() – 셋을 비웁니다.
  • set.size – 셋에 몇 개의 값이 있는지 세줍니다.

셋 내에 동일한 값이 있다면 set.add(value) 를 호출하더라도 반응을 안함. 이것이 셋 내에서 중복이 없는 이유.

방문자 방명록을 예시로 들자면, 한 방문자는 ‘단 한번만 기록’되어야 한다. 이때 적합한 자료구조가 바로 셋.

let set = new Set();

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

set.add(john);
set.add(pete);
set.add(mary);
set.add(john);
set.add(mary);

//john, mary가 두번 방문 했지만 방명록에는 한번만 작성됨
alert( set.size ); // 3

for (let user of set) {
  alert(user.name); // // John, Pete, Mary 순으로 출력
}

셋 대신 배열 사용해 방문자 정보를 저장한 후, 중복 값 여부는 배열 메서드인 arr.find()를 이용해 확인할 수도 있다. 하지만 arr.find는 배열 내 전체 요소를 뒤져 중복값을 찾기 때문에 셋보다 성능 면에서 떨어진다.

셋에서 반복 작업하기

for…of 나 forEach를 사용 가능.

let set = new Set(["oranges", "apples", "bananas"]);

for (let value of set) alert(value);

// forEach를 사용해도 동일하게 동작
set.forEach((value, valueAgain, set) => {
  alert(value);
});

이때 forEach에 쓰인 콜백 함수는 세 개의 인수를 받음. 첫번째, 두번째 둘다 같은 값을 받고 세번째는 목표하는 객체(셋)을 받는다. 첫번째 두번째 동일한 값이 인수에 등장하는 이유는 맵Map과의 호환성 때문. 맵의 forEach에 쓰인 콜백이 세 개의 인수를 받기 때문에 이렇게 구현해 놓으면 맵을 셋으로, 셋을 맵으로 교체하기 쉽다.

셋에도 맵과 마찬가지로 반복 작업을 위한 메서드가 있습니다.

  • set.keys() – 셋 내의 모든 값을 포함하는 이터러블 객체를 반환합니다.
  • set.values() – set.keys와 동일한 작업을 합니다. 맵과의 호환성을 위해 만들어진 메서드입니다.
  • set.entries() – 셋 내의 각 값을 이용해 만든 [value, value] 배열을 포함하는 이터러블 객체를 반환합니다. 맵과의 호환성을 위해 만들어졌습니다.

Set 활용법

  • 하나의 배열에서 중복된 값들을 없앤 배열을 만들고 싶을 때
let values = ["Hare", "Krishna", "Hare", "Krishna",
  "Krishna", "Krishna", "Hare", "Hare", ":-O"
];  //중복값들이 존재

function unique(arr) {
 return Array.from(new Set(arr));
}

const uniqueValues = unique(values);

출처

https://lakelouise.tistory.com/38

https://velog.io/@namda-on/JavaScript-Map-과-Object-의-차이

https://ko.javascript.info/map-set

Comments