요소가 한국어인 배열을 sort()로 정렬하기
설정한 조건에 따라 배열 안의 요소를 정렬해주는 sort() 메서드는 배열 안의 모든 요소를 '문자형'으로 변환한 후, 유니코드 단위의 값을 비교한 뒤 재정렬한다.
이때 배열 안의 요소 값이 '한국어'일 때 sort()를 사용하게 되면 설정한대로 오름차순, 내림차순으로 정렬이 이루어질까?
const kors = ['대한민국', '호주', '독일', '가나'];
const nums = ['100', '1', '3', '0', '000', '99'];
// 일반적인 sort
console.log(kors.sort((a, b) => a - b)); // [ '대한민국', '호주', '독일', '가나' ]
console.log(nums.sort((a, b) => a - b)); // [ '0', '000', '1', '3', '99', '100' ]
정답은 아니오🙅♂️다. a - b를 조건으로 걸었으니 가나다 순으로 가나가 제일 앞에 위치해야 하는데 배열의 정렬이 변하지 않았다. 한국어도 문자열인데 왜 sort했을 때 제대로 정렬되지 않을까?
console.log('대한민국' < '가나'); // false
sort()는 비교함수의 반환값이 0보다 작으면 a를 b보다 앞으로 정렬, 0보다 크면 b를 a보다 앞으로 정렬한다. 그런데 문자열끼리의 비교는 정수가 아닌 true, false의 boolean값으로 반환하기 때문에 sort()에서 제대로 동작하지 않는 것이다!
그렇다면 어떻게 비교를 해야 한국어가 들어있는 배열을 원하는대로 정렬할 수 있을까?
localeCompare를 이용해 요소가 한국어인 배열을 sort()로 정렬하기
console.log('대한민국'.localeCompare('가나')); // 1
String.prototype.localeCompare()
localeCompare(compareString, locales, options)
- compareString: referenceString이 비교되는 문자열
- 결과값: referenceString이 compareString 전 혹은 뒤에 오는지 또는 동등한지를 나타내는 정수를 반환
const kors = ['대한민국', '호주', '독일', '가나'];
const nums = ['100', '1', '3', '0', '000', '99'];
// 일반적인 sort
console.log(kors.sort((a, b) => a - b)); // [ '대한민국', '호주', '독일', '가나' ]
// localeCompare를 이용한 한글 sort
console.log(kors.sort((a, b) => a.localeCompare(b))); // [ '가나', '대한민국', '독일', '호주' ]
위와 같이 localeCompare()는 음수, 0, 양수로 값을 반환하기 때문에 내가 원하는 대로 sorting을 진행할 수 있다!
localeCompare를 이용해 특수 언어 비교하기
const a = 'réservé'; // 액센트 O, 소문자
const b = 'RESERVE'; // 액센트 X, 대문자
const c = 'ReSerVe';
const d = 'zebra';
console.log(a.localeCompare(b)); // 양수: b가 a보다 앞에 위치
console.log(a.localeCompare(b, 'en', { sensitivity: 'base' })); // 0: 동일
console.log(a.localeCompare(c, 'en', { sensitivity: 'base' })); // 0: 동일
console.log(a.localeCompare(d, 'en', { sensitivity: 'base' })); // -1: a가 d보다 앞에 위치
같은 reserve더라도 대/소문자인지, 액센트가 붙었는지 아닌지에 따라 다르게 표현되는데 localeCompare는 기준점을 잡고 각 문자들을 비교할 수 있다. 위의 예제와 같이 액센트가 붙어있는 a의 reserve와 대문자만으로 이루어진 b의 reserve를 기준점(sensitivity: 'base')을 잡고 비교해보면 두 문자가 같은 문자라는 결과를 반환해준다.
여기서의 sensitivity 옵션은 대소문자, 액센트, 케이스 및 다른 변형들에 대한 민감도를 제어하며 아래와 같은 옵션이 있다.
const a = 'a';
const d = 'A';
console.log(a.localeCompare(d, 'en', { sensitivity: 'base' })); // 0
console.log(a.localeCompare(d, 'en', { sensitivity: 'accent' })); // 0
console.log(a.localeCompare(d, 'en', { sensitivity: 'case' })); // -1
console.log(a.localeCompare(d, 'en', { sensitivity: 'variant' })); // -1
1. base: 기본 문자만을 고려해 비교하며, 액센트와 대소문자는 무시된다. 'a'와 'A', 'á', 'À'는 모두 동일하게 취급된다.
2. accent: 기본 문자와 액센트를 고려해 비교하며, 대소문자는 무시된다. 'a'와 'á'는 다르게 취급되지만, 'a'와 'A'는 동일하게 취급된다.
3. case: 기본 문자와 대소문자를 고려해 비교하며, 액센트는 무시된다. 'a'와 'A'는 다르게 취급되지만, 'a'와 'á'는 동일하게 취급된다.
4. variant: 기본 문자, 액센트, 대소문자를 모두 고려해 비교한다. 'a'와 'A', 'á'는 모두 다르게 취급된다.
[참고 자료]
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
https://oliviakim.tistory.com/43
'Front-End > JavaScript' 카테고리의 다른 글
[JavaScript] 객체 내부에서의 getter, setter (0) | 2024.08.19 |
---|---|
[JavaScript] 객체의 속성에 접근하는 점 표기법(마침표 표기법)과 대괄호 표기법 (ft. 좋은 코드) (0) | 2024.08.15 |
[JavaScript] JSON 알아보기 (0) | 2023.05.01 |
[JavaScript] 모던 자바스크립트의 특징 (0) | 2023.04.28 |
[프로그래머스 / JavaScript] Lv.2 피보나치 수 (0) | 2023.04.22 |