JavaScript - Map 정렬 (key 또는 value로 정렬)

Map은 key-value 형태로 요소를 저장하는 자료구조입니다. Map의 key 또는 value를 기준으로 정렬하는 방법을 소개합니다.

1. Spread 연산자와 sort()를 이용하여 Map 정렬

Spread operator를 사용한, [...mapObject]와 같은 표현은 key-value의 요소들이 배열에 저장된 형태로 리턴됩니다.

배열 객체에 대해서 sort()를 수행하면, key를 기준으로 배열이 정렬됩니다.

let myMap = new Map([
  ['c', 2],
  ['a', 4],
  ['d', 1],
  ['b', 3],
]);

let elementsArray = [...myMap];
console.log(elementsArray);

let sortedAscArray = [...myMap].sort();
console.log(sortedAscArray);

Output:

[ [ 'c', 2 ], [ 'a', 4 ], [ 'd', 1 ], [ 'b', 3 ] ]
[ [ 'a', 4 ], [ 'b', 3 ], [ 'c', 2 ], [ 'd', 1 ] ]

만약 정렬한 배열을 다시 Map으로 변환하고 싶다면, 아래와 같이 Map의 생성자의 인자로 정렬된 결과를 전달하면 됩니다.

let sortedAsc = new Map([...myMap].sort());

2. key를 기준으로 오름차순, 내림차순 정렬

sort()는 기본적으로 key를 오름차순으로 정렬합니다. 만약 내림차순으로 정렬하고 싶다면 오름차순으로 정렬된 결과를 reverse() 함수로 역순으로 바꾸면 내림차순 정렬이 됩니다.

let myMap = new Map([
  ['c', 2],
  ['a', 4],
  ['d', 1],
  ['b', 3],
]);

// Ascending
let sortedAsc = new Map([...myMap].sort());
console.log(sortedAsc);

// Decending
let sortedDsc = new Map([...myMap].sort().reverse());
console.log(sortedDsc);

Output:

Map(4) { 'a' => 4, 'b' => 3, 'c' => 2, 'd' => 1 }
Map(4) { 'd' => 1, 'c' => 2, 'b' => 3, 'a' => 4 }

2. value를 기준으로 오름차순, 내림차순 정렬 (value가 Number일 때)

기본적으로 sort()는 Map의 key를 정렬합니다.

만약 value로 정렬하고 싶을 때는 sort((a, b) => a[1] - b[1]))처럼 인자로 value의 크기를 비교하는 comparator 함수를 전달해야 합니다. 참고로, a[1]처럼 Index 1은 value 값을 의미하고, Index 0은 key 값을 의미합니다.

크기를 비교할 때 a[1] - b[1]처럼 - 연산자를 사용하였는데, value가 Number일 때 이것으로 크기를 비교할 수 있습니다. 만약 문자열이라면 다른 방식으로 비교해야하는데, 아래에서 다시 설명하겠습니다.

let myMap = new Map([
  ['c', 2],
  ['a', 4],
  ['d', 1],
  ['b', 3],
]);

// Ascending
let sortedByValueAsc = new Map([...myMap].sort((a, b) => a[1] - b[1]));
console.log(sortedByValueAsc);

// Decending
let sortedByValueDsc = new Map([...myMap].sort((a, b) => a[1] - b[1]).reverse());
console.log(sortedByValueDsc);

Output:

Map(4) { 'd' => 1, 'c' => 2, 'b' => 3, 'a' => 4 }
Map(4) { 'a' => 4, 'b' => 3, 'c' => 2, 'd' => 1 }

3. value를 기준으로 오름차순, 내림차순 정렬 (value가 String일 때)

아래 예제와 같이 value가 string 타입일 때, (a, b) => a[1] - b[1])와 같은 표현으로 정렬하면 정렬이 안됩니다. 문자열을 비교할 때 -로 크기 비교가 안되기 때문인 것 같은데요.

a.localeCompare(b)로 문자열의 크기를 비교하도록 구현하면 됩니다.

let myMap = new Map([
  [2, 'c'],
  [4, 'a'],
  [1, 'd'],
  [3, 'b'],
]);

// Ascending
let sortedByValueAsc = new Map([...myMap].sort((a, b) => a[1].localeCompare(b[1])));
console.log(sortedByValueAsc);

// Decending
let sortedByValueDsc = new Map([...myMap].sort((a, b) => a[1].localeCompare(b[1])).reverse());
console.log(sortedByValueDsc);

Output:

Map(4) { 4 => 'a', 3 => 'b', 2 => 'c', 1 => 'd' }
Map(4) { 1 => 'd', 2 => 'c', 3 => 'b', 4 => 'a' }

참고로, 내림차순으로 정렬할 때, reverse()로 오름차순 정렬을 역순으로 바꾸는 대신에, 아래와 같이 Arrow function의 비교 연산을 변경하여 내림차순으로 바로 정렬하도록 구현할 수도 있습니다.

// Decending
// let sortedByValueDsc = new Map([...myMap].sort((a, b) => a[1].localeCompare(b[1])).reverse());
let sortedByValueDsc = new Map([...myMap].sort((a, b) => b[1].localeCompare(a[1])));
Loading script...
codechachaCopyright ©2019 codechacha