문제 상황
숫자와 문자열이 섞여 있는 하나의 배열을 입력받아, 숫자는 오름차순으로 먼저 정렬하고 그 뒤에 문자열은 알파벳순으로 정렬한 단일 배열을 반환하는 JavaScript 함수를 작성해야 합니다.
여기서 중요한 조건은 정렬 과정에서 각 값의 원래 자료형(number, string)이 그대로 유지되어야 한다는 점입니다.
해결 코드
배열의 sort() 메서드에 커스텀 비교 함수를 전달하면 이 문제를 손쉽게 해결할 수 있습니다. 다음은 전체 코드입니다 −
const arr = [5, 8, 'car', 'dad', 'amber', 1, 12, 76, 'bat'];
const separateSort = (arr = []) => {
const sorter = (a, b) => {
if(typeof a === 'number' && typeof b === 'string'){
return -1;
};
if(typeof a === 'string' && typeof b === 'number'){
return 1;
};
if(typeof a === 'string' && typeof b === 'string'){
return a.charCodeAt(0) - b.charCodeAt(0);
};
return a - b;
};
const res = arr.sort(sorter);
return res;
};
console.log(separateSort(arr));
실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다 −
[
1, 5,
8, 12,
76, 'amber',
'bat', 'car',
'dad'
]
코드 동작 원리
핵심은 sorter라는 이름의 비교 함수입니다. JavaScript의 sort() 메서드는 두 요소를 인자로 받는 비교 함수의 반환값에 따라 요소들의 순서를 결정합니다.
- -1 반환: 첫 번째 요소(a)가 두 번째 요소(b)보다 앞에 위치합니다.
- 1 반환: 첫 번째 요소(a)가 두 번째 요소(b)보다 뒤에 위치합니다.
비교 함수의 로직을 살펴보면 다음과 같습니다.
먼저 a가 숫자이고 b가 문자열이면 -1을 반환하여 숫자가 항상 문자열보다 앞에 오도록 합니다. 반대로 a가 문자열이고 b가 숫자이면 1을 반환해 순서를 뒤집습니다. 두 값이 모두 문자열인 경우에는 charCodeAt(0)으로 각 문자열의 첫 글자의 유니코드 값을 비교하여 알파벳순으로 정렬합니다. 마지막으로 두 값이 모두 숫자인 경우에는 일반적인 뺄셈(a - b)으로 오름차순 정렬을 수행합니다.
이처럼 자료형을 판별하는 분기 처리만 추가하면, 혼합된 타입의 배열도 원하는 기준에 따라 깔끔하게 정렬할 수 있습니다.