타닥타닥 개발자의 일상

Map 을 이용해서 다양한 형태의 key값을 가지는 구조체 만들기 / Array, Set의 보완 / Map 구조체의 메서드 알아보기 본문

코딩 기록/JavaScript

Map 을 이용해서 다양한 형태의 key값을 가지는 구조체 만들기 / Array, Set의 보완 / Map 구조체의 메서드 알아보기

NomadHaven 2023. 5. 31. 09:59

 

자바스크립트에는 다양한 형태의 구조체가 있다.

array는 element별로 인덱스가 있고 인덱스 별로 요소를 구분, 외부에서 요소를 호출도 가능하다. 단점은 요소별로 중복된 값이 있을때 중복 값을 제거하거나 중복된 인수의 값을 구하기가 번거롭다는 점이다.

 

 Set는 중복된 element를 여러번 추가해도 고유한 element 하나만 요소로 가지는 특징이 있다. 따라서 배열내의 중복값을 제거하거나 고유한 요소의 수를 파악할때 좋은 구조체이다. 단점은 Set에는 인덱스가 없다. 따라서 외부에서 Set내의 element를 key값을 통해서 호출하지 못한다. 

 

array와 Set의 아쉬운 점을 보완하는 구조체가 바로 Map이다.

 

그렇다면 Map의 사용 사례를 알아보자.

const rest = new Map();
rest.set('name', 'Classico Italiano');
rest.set(1, 'Firenze', 'Italy');

console.log(rest.set(2, 'Lisbon', 'Portugal'));

rest라는 이름의 Map 구조체를 new Map(); 을 통해 생성한다.

해당 구조체에 key,value값을 추가하고 싶으면 .set(key,value) 메소드를 쓰면 된다.

 

첫번째 key/value 값으로 name/Classico Italinao

두번째 key/value 값으로 1/ Firenze, Italy

세번재 key/value 값은 console 창 출력을 통해서 2/Lisbon,Portugal 이 추가되었다.

 

그렇다면 실제 콘솔창에서는 어떻게 출력될까?

첫번째 key/value 값으로 name/Classico Italinao 는 그대로 추가 되었다.

두번째 key/value 값으로 1/ Firenze만 출력되었다, Italy는 없다.

세번재 key/value 값은 console 창 출력을 통해서 2/Lisbon 만 출력되었다. Portugal은 없다.

 

.set(key,value) 형식으로 Map에 값을 추가할 때,

key,value 값 다음에 다른 값을 추가해도key,value 값만 추가 됨을 알수 있다.

또한 name이라는 key값처럼 string이 key 값이 될수도 있지만, 1,2 처럼 숫자가 key 값이 될수도 있다.

 

 

그렇다면 계속 .set() 메서드를 이용해서 Map에 값을 추가해보도록 하자

rest
  .set('categories', ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'])
  .set('open', 11)
  .set('close', 23)
  .set(true, 'We are open')
  .set(false, 'We are closed');

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

차례로 name이라는 key값을 get 메서드를 통해 value 호출,

'true'라는 문자열 key값을 get 메서드를 통해 value 호출,

true라는 boolean key값을 get 메서드를 통해 value 호출,

'1'이라는 문자열 key값을 get 메서드를 통해 value 호출,

1이라는 숫자 key값을 get 메서드를 통해 value 호출.

 

결과를 살펴보자.

 

차례로 name이라는 key값을 get 메서드를 통해 value 호출 👉Classico Italiano라는 value 값 호출

'true'라는 문자열 key값을 get 메서드를 통해 value 호출👉 true라는 문자열 key값이 존재하지 않는다 처리해 undefined.

true라는 boolean key값을 get 메서드를 통해 value 호출👉true라는 boolean의 value값인 'We are Open" 호출

'1'이라는 문자열 key값을 get 메서드를 통해 value 호출👉 1이라는 문자열 key값이 존재하지 않는다 처리해 undefined.

1이라는 숫자 key값을 get 메서드를 통해 value 호출👉1이란 숫자 key값의 value 값인 Firenze 호출

 

이를 통해서 Map 구조체는 key값이 string인지, 숫자인지, boolean인지 모두 구분 가능하다는 사실을 알게 되었다.

그렇다면 이렇게 key 값이 구분 가능한 Map을 어떻게 활용할 수 있을까?

 

 

const time = 21;
console.log(rest.get(time > rest.get('open') && time < rest.get('close')));

21이라는 값을 가지는 time 값이 'open'의 value 값 보다 크고 close 보다 작을 경우를 가정헀을때 해당 사실은 참이다.

따라서 출력문 안에 있는 조건은 true가 된다.

또한 rest에서 true라는 키값이 가지는 value는 'We are Open'이다.

따라서 true의 value 값인 we are open이 출력된다.

어떠한 값에 대한 조건이 true, false 일때 이에 대한 값을 출력할수 있도록 Map에서 만들수 있다.

 

또한 Map 구조체는 해당 구조체 안에 특정한 값이 있는지 역시 확인 가능하다.

해당 구조체 안의 element를 삭제하는 것 역시 가능하다.

해당 구조체 안에 몇개의 element가 있는지 확인하는 것도 가능하다.

 

아래는 has / delete / size 메서드를 통해서 확인, 삭제, 갯수 확인을 한 코드이다.

//Map 구조체 안에 특정한 요소가 있는지 확인하는 메서드 has
console.log(rest.has('categories')); //true

//Map 구조체 안에 특정한 요소를 삭제하는 메서드 delete
rest.delete(2);
console.log(rest.has(2)); //false

//Map 구조체 안에 있는 요소의 개수를 확인하는 메서드 size
console.log(rest.size); //7

 

출력 결과

위에서 말했듯 Map 구조체는 string, boolean, number 을 구분해서 key 값을 처리한다.

그렇다면 Map 구조체의 key값으로 array배열도 처리가 가능할까?

 

 

[1,2] 라는 배열을 key값으로 추가하고 'Test'라는 Value를 추가했다.

rest.set([1, 2], 'Test');
console.log(rest); //key: (2) [1, 2] value: "Test"

Map 구조체 전체를 출력헀을 시에는 7번 인덱스에 key 값으로 배열 [1,2]가 잘 들어간 것이 보인다.

하지만 해당 값을 출력하면

console.log(rest.get([1, 2]));

undefine이 출력된다.

 

왜 이렇게 되나 chatGPT 한테 물어보니까.

 

rest.get([1, 2])에서 [1, 2]는 배열로 키로 사용되고 있습니다.
그러나 Map의 get() 메서드는 키를 정확히 일치하는 값으로 찾기 위해 동등성 비교(===)를 수행합니다.

배열은 참조 타입이므로 동등성 비교를 할 때는 같은 참조를 가리켜야 일치합니다.
console.log(rest.get([1, 2])); 부분에서 [1, 2]는 배열 객체를 생성하여 사용한 것입니다.
이 때, 코드가 실행될 때마다 [1, 2]라는 배열 객체가 매번 새롭게 생성됩니다.

따라서, rest.get([1, 2])는 매번 새로운 배열 객체로 인식되어,
기존에 rest Map에 저장된 [1, 2]와 일치하는 키를 찾지 못하고 undefined를 반환하게 됩니다.

라고 한다.

 

이럴땐 그럼 어떻게 배열을 Map의 key값으로 사용할수 있을까?

 const 를 이용해서 먼저 배열을 선언해주면 된다.

//배열을 key로 사용하기 위해선 const를 사용해서 배열을 선언
const arr = [1, 2];
rest.set(arr, 'Test');
console.log(rest.get(arr)); //Test

위와 같이 arr를 통해서 먼저 선언된 배열을  key값으로 추가하면 get 메서드로 key값을 찾아도 Test라는 Value가 잘 호출된다.

 

 

 

Map의 독특한 기능은 DOM도 key 값으로 쓸수 있다는 점이다.

rest.set(document.querySelector('h1'), 'Heading'); //콘솔창에서 key 클릭하면 hi부분 하이라이트됨
console.log(rest);

위의 코드처럼  h1을 지정한 DOM 을 key 값으로 넣은 다

전체 구조체를 클릭한다 하자.

 

출력된 key값인 h1을 클릭하면

콘솔창의 웹페이지에서 h1 부분에 해당하는 문자열이 하이라이트 처리된다.

 

 

Comments