[Javascript] Map 정리

세하·2025년 6월 24일

JavaScript

목록 보기
2/10

Map은 키(key) - 값(value) 쌍을 저장하는 내장 객체

객체 {}와의 차이점

특징Map일반 객체 {}
키 타입모든 자료형 가능 (객체 포함)문자열, 심볼만 가능
키 순서입력 순서 유지보장되지 않음
접근 방법map.get(key) / map.set(key, val)obj[key] 또는 obj.key
키 존재 확인map.has(key)key in obj 또는 obj.hasOwnProperty(key)
크기 확인map.size직접 계산 (Object.keys(obj).length)

순서에 대해 조금 더 자세히 말해보자면
요즘 대부분의 JS 엔진은 삽입 순서대로 출력한다.
하지만! Object는 명확하게 순서를 보장하지는 않음
특히 숫자형 키를 쓰면 순서가 자동 정렬되기도 함

const obj = {};
obj[2] = 'two';
obj[1] = 'one';
console.log(obj); // { '1': 'one', '2': 'two' } ← 숫자 키는 정렬됨!

만약 순서를 보장하고싶다면 Map 사용을 권장.
Map은 입력한 순서를 반드시 유지
숫자 키를 써도 절대 정렬되지 않음

값에 접근

Map은 .get()과 .set()만 사용해야 하며, []로는 값에 접근할 수 없음
Object는 [] 또는 .로 접근 가능하며, 숫자 키는 자동으로 문자열로 변환됨

let map = new Map();
map.set(1, 'one');
console.log(map.get(1));  // "one"
console.log(map[1]);      // undefined 
let obj = {};
obj[1] = 'one';           // 숫자 → 문자열 '1'
console.log(obj[1]);      // "one" 
console.log(obj['1']);    // "one" 

주요 메서드

메서드설명
new Map()빈 맵 생성
map.set(key, value)key에 value 저장
map.get(key)key에 해당하는 value 반환 (없으면 undefined)
map.has(key)key가 존재하는지 여부 반환
map.delete(key)key-value 쌍 삭제
map.clear()모든 요소 삭제
map.size요소 개수 반환
let map = new Map();

map.set('a', 1);
map.set('b', 2);
map.set('b', 3); // 이미 존재하는 키를 또 set하려고 함

console.log(map.get('a')); // 1
console.log(map.has('b')); // true
console.log(map.get('b'));  // 3
console.log(map.size);      // 2 (변하지 않음)

Map 객체에서 키는 고유(unique) 해야 함.
map.set('b', 3)는 이미 존재하는 키 'b'의 값을 3으로 덮어씌우게 됨.

순회하기

  1. [key, value] 형태의 쌍을 순회
  • for...of (내부적으로 map.entries()를 사용)
const map = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3]
]);

for (const [key, value] of map) {
  console.log(key, value);
}

const map = new Map([
  ['a', [1, 2]],
  ['b', [3, 4]],
]);

for (const [key, value] of map) {
  value.push(99); // 가능! map 내부의 배열도 변경됨
  map.set(key, [...value, 999]); //  새로운 배열로 대체 (불변성 유지하고 싶을 때)
}
  • map.entries()
for (const [key, value] of map.entries()) {
  console.log(key, value);
}
// 출력:
// a 1
// b 2
// c 3
  1. map.keys()
const map = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3]
]);

for (const key of map.keys()) {
  console.log(key);  
}
// 출력:
// a
// b
// c
  1. map.values()
for (const value of map.values()) {
  console.log(value);
}
// 출력:
// 1
// 2
// 3

주의할점

  1. 문자열 변환 비교 실수
if (`${value}` === 1)  // flase : 문자열 '1' === 숫자 1
  • 항상 타입 일치 확인: value === 1
  1. 키 타입 주의 (1과 "1"은 다른 키)
map.set(1, "number");
map.set("1", "string");

console.log(map.get(1));   // "number"
console.log(map.get("1")); // "string"
  1. 배열 index처럼 사용 ❌
map[0] // 사용 불가
  • map.get(key)을 사용해야 함

예제

  1. 빈도수 세기 (문자나 숫자 중복 카운팅)
const arr = [1, 1, 2, 3, 2, 4];
const map = new Map();

for (const num of arr) {
  map.set(num, (map.get(num) || 0) + 1);
}

console.log(map); // Map { 1 => 2, 2 => 2, 3 => 1, 4 => 1 }
  1. 조건에 맞는 키 추출
const answer = [];
for (const [key, value] of map) {
  if (value === 1) {
    answer.push(key);
  }
}

정렬하기

  1. value기준(숫자)으로 오름차순

    let map = new Map([
      ['a', thisTurn[0]],
      ['b', thisTurn[1]],
      ['c', thisTurn[2]]
    ]);
    
    // 1. Map을 배열로 변환
    let sortedEntries = [...map.entries()].sort((a, b) => a[1] - b[1]);
    
    // 2. 다시 Map으로 변환
    let sortedMap = new Map(sortedEntries);
    
    // 출력 확인
    for (const [key, value] of sortedMap) {
      console.log(key + "=" + value);
    }

    map.entries()는 [key, value] 형태의 배열 iterator를 반환
    sort((a, b) => a[1] - b[1]): value 기준으로 정렬 (a[1], b[1]이 value)
    다시 new Map(...)으로 감싸면 정렬된 Map 객체 생성됨

  2. key기준(문자)으로 오름차순

  • 기본

    let map = new Map([
      ['b', 20],
      ['a', 10],
      ['c', 30]
    ]);
    
    // 1. entries 배열로 변환 후 key 기준 정렬
    let sortedEntries = [...map.entries()].sort((a, b) => {
      if (a[0] < b[0]) return -1;
      if (a[0] > b[0]) return 1;
      return 0;
    });
    
    // 2. 다시 Map으로 만들기
    let sortedMap = new Map(sortedEntries);
    
    // 확인 출력
    for (const [key, value] of sortedMap) {
      console.log(key + "=" + value);
    }
  • localCompare 사용하여 정렬

    let sortedMap = new Map([...map.entries()].sort((a, b) => a[0].localeCompare(b[0])));

    localeCompare는 문자열 비교 함수라서 알파벳 순서대로 정확하게 정렬됨
    숫자 키라면 a[0] - b[0] 써도 됨

key 존재 여부 판단 + value 가져오기

let map = new Map();
map.set("numbers", [1, 2, 3]);

let key = "numbers";

if (map.has(key)) {
  let numbersArray = map.get(key);
  console.log("숫자 목록:", numbersArray); // 숫자 목록: [ 1, 2, 3 ]
}

value가 배열일 때

정렬

  1. 숫자 (아래 예시에서는 value) 기준 오름차순
let arrMap = new Map([
	[a, [Math.abs(card - aLast), aLast]],
	[b, [Math.abs(card - bLast), bLast]],
	[c, [Math.abs(card - cLast), cLast]],
	[d, [Math.abs(card - dLast), dLast]]
]);

이걸 Math.abs(card - aLast) 값 기준으로 정렬하고싶으면?

let sortedArrMap = new Map(
	[...arrMap.entries()].sort((a, b) => a[1][0] - b[1][0])
);
  1. 문자 (예시에서는 key) 기준 오름차순
let sortedMap = new Map([...map.entries()].sort((a, b) => a[0].localeCompare(b[0])));
  • localeCompare는 문자열 비교 함수라서 알파벳 순서대로 정확하게 정렬

순회

let arrMap = new Map([
	[a, [Math.abs(card - aLast), aLast]],
	[b, [Math.abs(card - bLast), bLast]],
	[c, [Math.abs(card - cLast), cLast]],
	[d, [Math.abs(card - dLast), dLast]]
]);
		
for (const [key, [diff, last]] of m) {
	console.log(`${key}: 차이=${diff}, 마지막값=${last}`);
}

Map은 배열이 아니기 때문에 인덱스로 접근할 수 없다!

let arrMap = new Map([
  [a, [Math.abs(card - aLast), aLast]],
  [b, [Math.abs(card - bLast), bLast]],
  [c, [Math.abs(card - cLast), cLast]],
  [d, [Math.abs(card - dLast), dLast]]
]);

위의 구조는 아래와 같음

Map {
  a => [diffA, aLast],
  b => [diffB, bLast],
  c => [diffC, cLast],
  d => [diffD, dLast]
}

❓ 만약 cLast에 접근하려면?

arrMap.get(c)[1]
  • arrMap.get(c) : [Math.abs(card - cLast), cLast]
  • 그중 1번 인덱스 → cLast

Map의 첫 번째 요소의 value 중 두 번째 값에 접근하기

let sortedArrMap = new Map([
	[a, [Math.abs(card - aLast), aLast]],
	[b, [Math.abs(card - bLast), bLast]],
	[c, [Math.abs(card - cLast), cLast]],
	[d, [Math.abs(card - dLast), dLast]]
]);
  1. entries()로 접근
    const firstEntry = [...sortedArrMap.entries()][0]; // [key, [diff, last]]
    const secondOfFirstValue = firstEntry[1][1];        // aLast
  1. values()로 접근
    const firstValue = [...sortedArrMap.values()][0]; // [diff, last]
    const secondOfFirstValue = firstValue[1];         // aLast
첫 번째 value[...sortedArrMap.values()][0]
그 value의 두 번째 값 (value[1])[...sortedArrMap.values()][0][1]
또는 entries 기준으로 접근[...sortedArrMap.entries()][0][1][1]

key에 접근할때도 key()로 배열로 변환해서 접근

let selectedArr = [...sortedArrMap.keys()][0];

Map의 key로 배열을 사용하면 key는 해당 배열 자체를 참조하고있다.(수정 작업 가능)

  1. 실제로 a의 배열에 card가 추가됨
    let arrMap = new Map([
      [a, [Math.abs(card - aLast), aLast]],
      ...
    ]);
    
    a.push(card);
  1. key가 배열 중 하나이므로 실제 배열이 바뀜
    for (const [key, [_, last]] of arrMap) {
      key.push(777);
    }
  1. selectedKey가 가리키는 key를 수정함
    let selectedKey;
    if (firstIndexValue[0] != secondIndexValue[0]){
    		selectedKey = [...sortedArrMap.keys()][0]; // 첫 번째 key. 즉, 배열 a~d 중 하나
    		if (card < firstIndexValue[1]){
    			selectedKey.push(card); //그 키를 수정해도 반영이 됨!!! 실제 배열 a~d 중 하나가 여기서 변경됨!!!
  1. 예시 코드
    let a = [10];
    let b = [20];
    let arrMap = new Map([
      [a, ['A']],
      [b, ['B']]
    ]);
    
    let selectedKey = [...arrMap.keys()][0];
    selectedKey.push(99);
    
    console.log(a); // [10, 99] : a 자체가 바뀜!!!

Map에서 key로 value값 가져오기

let result = new Map([
  ["A", 0],
  ["B", 0],
  ["C", 0]
]);

result.get("A"); // 0

Map에서 value값 갱신하기

let result = new Map([
  ["A", 0],
  ["B", 0],
  ["C", 0]
]);

let penalty = 5;

for (const key of result.keys()) {
  result.set(key, result.get(key) + penalty);
}

console.log([...result.entries()]);
// [ [ 'A', 5 ], [ 'B', 5 ], [ 'C', 5 ] ]

0개의 댓글