Front-End/JavaScript

[JavaScript] 특수 언어가 있는 문자열 배열을 정렬하는 방법, localeCompare()

Olivia Kim 2024. 7. 23. 00:54
반응형

요소가 한국어인 배열을 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

 

String.prototype.localeCompare() - JavaScript | MDN

localeCompare() 메서드는 참조 문자열이 정렬 순으로 지정된 문자열 앞 혹은 뒤에 오는지 또는 동일한 문자열인지 나타내는 수치를 반환합니다.

developer.mozilla.org

https://oliviakim.tistory.com/43

 

[JavaScript] .sort() 함수를 이용해 배열의 요소 정렬하기

설명 Array.prototype.sort()는 배열의 요소를 적절한 위치에 정렬한 후, 그 배열을 반환한다. 이때 배열 안 모든 요소는 문자형으로 변환된 후, 유니코드 단위의 값을 비교한 뒤 재정렬된다. 배열 안의

oliviakim.tistory.com

 

 

반응형