Maps(data structure)

Juyeon Lee·2024년 8월 2일
0

Map: data structure that we can use to map values to keys. map can have any type of key.

Map: 다양한 타입의 값을 키로 사용할 수 있는 데이터 구조

Map은 모든 타입을 키로 가질 수 있다는 점에서 객체와 다르다. 객체는 키를 문자열로밖에 가질 수 없다.

Map을 만드는 방법은 다음과 같다.

const rest = new Map();
rest.set('name','lingling');
rest.set(1, 'Hongkong');
rest.set(2, 'Lisbon');

rest.set('categories',['Italian','Pizzaria','vagetrain'])
    .set('open', 11)
    .set('close',23)
    .set(true,'we are open')
    .set(false, 'we are closed')

먼저 빈 Map을 new Map()로 만들어주고 set으로 내용을 넣어준다. Map의 값을 가져오는 방법은 get 메서드를 사용한다.

console.log(rest.get('name'))
console.log(rest.get(true))
console.log(rest.get(1))

Map에서 키의 존재 여부를 확인하거나 키를 삭제하는 방법은 아래와 같다.

console.log(rest.has('categories')); // true
rest.delete(2);
console.log(rest.size); // 5

Map의 키로 배열을 사용할 수도 있지만, 아래 예제와 같이 직접 배열을 사용하면 예상과 다른 결과가 나올 수 있다.

rest.set([1, 2], 'Test');

console.log(rest.get([1,2])) 
//undeifned it's not the same object in the heap

위 코드에서 get([1, 2])가 undefined를 반환하는 이유는 배열이 객체이기 때문에 똑같아 보이는 배열도 서로 다른 메모리 주소를 가지기 때문이다.

따라서, 배열을 키로 사용할 때는 변수에 배열을 정의하고 그 변수를 키로 사용해야 한다.

const arr = [1,2]
rest.set(arr,'Test')
console.log(rest)
console.log(rest.size)
// rest.clear()

console.log(rest.get(arr))

이렇게 하면 동일한 배열 객체를 참조하므로 get 메서드가 올바르게 동작하게 된다.

Map을 만들어주는 다른 방법도 있는데 그걸 알아보자. 위에서는 빈 맵을 만들어주고 set으로 그 안을 채운 뒤 get으로 내용을 얻는 것이었는데, 처음부터 Map을 채워서 만들 수 있다. 아래의 코드를 보자.

const question = new Map([
  ['question',
   'What is the best programming language in the world?'],
  [1,'C'],
  [2,'Java'],
  [3,'Javascript'],
  ['correct',3],
  [true, 'Correct'],
  [false,'Try again!']
])

console.log(question)

위의 코드를 보면 알 수 있듯이 객체에서 키와 벨류를 모두 루프할 수 있게 해주는 Object.entries와 아주 비슷하게 생겼다. 그래서 객체를 Map 형태로 변환해주는 방법은 아래와 같다.

const hoursMap = new Map(Object.entries(openingHours));
console.log(hoursMap)

객체를 Map으로 변환하는 이유는 객체는 iterable하지 않지만 Map은 iterable하기 때문에 루프해주고 싶을 때 Map으로 변환해주면 편리하다.

다음으로 iterable한 Map을 루프하는 코드를 보자.

console.log(question.get('question'))
for(const [key,value] of question){
  if(typeof key === 'number') 
  console.log(`Answer ${key}: ${value}`)
}

const answer = Number(prompt('Your answer'));
console.log(question.get(question.get('correct') === answer))

question 맵을 for of로 루프한 뒤, key가 number일 때 콘솔에 찍히게 해두었다. 결과는 이렇게 나온다.

Answer 1: C
Answer 2: Java
Answer 3: Javascript

여기에 유저가 답을 적을 수 있게 prompt를 넣어주고, key값 숫자가 일치해야 하므로 Number 형변환을 해준 것이다. 그래서 결과가 correct 값과 같으면 true이므로 question.get으로 'Correct'가 결과로 프린트된다.

Map을 array로 바꾸는건 이렇게 하면 된다.

console.log(([...question]))
console.log(...question.entries())
console.log(...question.keys())
console.log(...question.values())

이렇게 하면 Map을 다양한 형태의 배열로 변환할 수 있다.

마지막으로 언제 Object를 쓰고 언제 Map을 써야 하는지 알아보자.

Object를 사용할 때:

  • 메서드에 함수를 추가해야 할 때: 객체는 프로토타입을 상속받기 때문에 메서드를 추가하고 상속받은 메서드를 사용할 수 있다.
  • JSON 형식을 사용해야 할 때: JSON은 객체 표기법을 사용하므로, JSON 데이터와 호환되게 작업할 때는 객체를 사용해야 한다.

Map을 사용할 때:

  • 키를 문자열 아닌 다른 타입으로 사용하고 싶을 때: Map은 모든 타입의 키를 가질 수 있다. 객체는 키를 문자열로만 가질 수 있는 반면, Map은 숫자, 객체, 함수 등 다양한 타입을 키로 사용할 수 있다.
  • 순서가 중요한 데이터를 다룰 때: Map은 삽입된 순서대로 요소를 순회할 수 있다. 이는 객체와 달리 순서가 보장되기 때문에 순서가 중요한 경우 Map을 사용하는 것이 좋다.
  • 키의 개수가 많고 빈번한 삽입/삭제가 있는 경우: Map은 성능 면에서 객체보다 더 나은 성능을 보일 수 있다. 특히, 키의 개수가 많거나 빈번한 삽입과 삭제가 이루어질 때 Map을 사용하는 것이 유리하다.

0개의 댓글