문제 상황
다음과 같이 점(.)으로 구분된 숫자들로 이루어진 문자열 배열이 있다고 가정해 보겠습니다.
const arr = [ '.0', '.1', '.2', '.4', '.2.1', '.3', '.4.1', '.5', '.5.1.5' ];
이 배열을 사람이 보기에 자연스러운 오름차순으로 정렬하는 JavaScript 함수를 작성해야 합니다.
즉, '.0'이 가장 먼저 오고, 그다음 '.1', '.2', '.3' 순으로 정렬되며, 하위 단계를 포함한 문자열(예: '.2.1')은 해당 상위 항목 바로 뒤에 위치해야 합니다. 따라서 정렬이 완료된 배열은 다음과 같은 모습이 됩니다.
const output = [ '.0', '.1', '.2', '.2.1', '.3', '.4', '.4.1', '.5', '.5.1.5' ];
정렬 로직 구현하기
핵심 아이디어는 각 문자열을 점(.)을 기준으로 분리한 뒤, 각 세그먼트를 정수로 변환하여 왼쪽부터 차례대로 비교하는 것입니다. 하나라도 크기가 다른 세그먼트가 발견되면 즉시 비교 결과를 반환하고, 모든 공통 세그먼트가 동일하다면 세그먼트 개수가 적은 쪽이 앞에 오도록 처리합니다.
예제 코드
const arr = [ '.0', '.1', '.2', '.4', '.2.1', '.3', '.4.1', '.5', '.5.1.5' ];
const compare = (a, b) => {
if (a === b) {
return 0;
}
const aArr = a.split("."), bArr = b.split(".");
for (let i = 0; i < Math.min(aArr.length, bArr.length); i++) {
if (parseInt(aArr[i]) < parseInt(bArr[i])) {
return -1;
}
if (parseInt(aArr[i]) > parseInt(bArr[i])) {
return 1;
}
}
if (aArr.length < bArr.length) {
return -1;
}
if (aArr.length > bArr.length) {
return 1;
}
return 0;
};
arr.sort(compare);
console.log(arr);
실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
[
'.0', '.1',
'.2', '.2.1',
'.3', '.4',
'.4.1', '.5',
'.5.1.5'
]
동작 원리 정리
이 비교 함수는 Array.prototype.sort() 메서드의 콜백으로 전달되며, 두 문자열 a와 b의 대소 관계에 따라 음수, 양수 또는 0을 반환합니다. 각 세그먼트를 parseInt()로 숫자화했기 때문에 문자열 기준 정렬에서 발생할 수 있는 잘못된 순서(예: '.10'이 '.9'보다 앞에 오는 문제)를 방지할 수 있습니다. 이러한 방식은 소프트웨어 버전 번호나 계층적 목차 번호처럼 점으로 구분된 다단계 숫자 데이터를 정렬할 때 특히 유용하게 활용됩니다.