JavaScript에서는 문자열을 인자로 받아 해당 문자열이 알파벳 순서대로 정렬되어 있는지 확인하는 함수를 작성할 수 있습니다. 여기서 "정렬됨"은 오름차순 또는 내림차순 어느 한 방향으로 일관되게 배치되어 있음을 의미합니다.
예시
isSorted('adefgjmxz'); // true → 오름차순으로 정렬됨
isSorted('zxmfdba'); // true → 내림차순으로 정렬됨
isSorted('dsfdsfva'); // false → 오름차순/내림차순이 섞여 있어 정렬되지 않음
구현 코드
다음은 문자열이 정렬되어 있는지 확인하는 JavaScript 코드입니다.
const str = 'abdfhlmxz';
// 두 문자의 유니코드 코드 값 차이를 계산하는 헬퍼 함수
const findDiff = (a, b) => a.charCodeAt(0) - b.charCodeAt(0);
const isStringSorted = (str = '') => {
// 길이가 2 미만인 문자열은 항상 정렬된 것으로 간주
if (str.length < 2) {
return true;
}
let res = '';
for (let i = 0; i < str.length - 1; i++) {
if (findDiff(str[i + 1], str[i]) > 0) {
res += 'u'; // 오름차순 구간
} else if (findDiff(str[i + 1], str[i]) < 0) {
res += 'd'; // 내림차순 구간
}
// 오름차순과 내림차순이 동시에 존재하면 정렬되지 않은 문자열
if (res.includes('u') && res.includes('d')) {
return false;
}
}
return true;
};
console.log(isStringSorted(str));
출력 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
true
코드 설명
- findDiff: 인접한 두 문자의
charCodeAt()값을 비교하여 차이를 반환합니다. 양수면 다음 문자가 더 큰(오름차순) 경우, 음수면 더 작은(내림차순) 경우입니다. - 방향 기록: 반복문을 돌며 각 구간의 정렬 방향을 'u'(오름차순) 또는 'd'(내림차순) 문자로 누적합니다.
- 혼합 여부 검사: 문자열 중간에 오름차순과 내림차순이 동시에 나타나면 즉시
false를 반환하고, 끝까지 혼합되지 않으면true를 반환합니다. - 경계 처리: 길이가 1 이하인 문자열은 비교 대상이 없으므로 항상 정렬된 것으로 처리합니다.
참고로 방향 검사 시 indexOf()보다 includes()를 사용하는 것이 안전합니다. indexOf()는 첫 번째 위치에서 요소를 찾으면 0을 반환하는데, 이 값은 falsy로 평가되기 때문에 의도치 않은 논리 오류가 발생할 수 있습니다.
더 간단한 대안 방법
문자열을 배열로 변환한 뒤 정렬하여 원본과 비교하는 방식으로도 확인할 수 있습니다.
const isSortedAsc = (str = '') => [...str].sort().join('') === str;
const isSortedDesc = (str = '') => [...str].sort().reverse().join('') === str;
console.log(isSortedAsc('adefgjmxz')); // true
console.log(isSortedDesc('zxmfdba')); // true
console.log(isSortedAsc('dsfdsfva')); // false
이 방법은 코드가 간결하지만 문자열 전체를 정렬해야 하므로, 길이가 매우 긴 문자열에서는 앞서 소개한 단일 패스(single pass) 방식이 더 효율적입니다.