이번 글에서는 숫자 배열을 인수로 받아, 배열의 요소들이 오름차순으로 정렬되어 있는지, 내림차순으로 정렬되어 있는지, 아니면 정렬되어 있지 않은 상태인지 판별하는 JavaScript 함수를 작성해 보겠습니다.
함수는 다음과 같은 조건을 처리해야 합니다.
- 배열에 요소가 하나뿐이라면 정렬 여부를 판단할 수 없으므로
'not enough items'(요소가 부족함)라는 메시지를 반환해야 합니다. - 배열의 모든 요소가 서로 같다면
'all items are equal'(모든 요소가 같음)이라는 메시지를 반환해야 합니다.
동작 원리
핵심 로직은 간단합니다. 배열의 이웃한 두 요소를 차례대로 비교하면서 정렬 방향을 추적하는 것입니다.
- 먼저
ascending변수를null로 초기화하여 아직 정렬 방향이 결정되지 않았음을 표시합니다. - 배열을 한 칸 앞당긴 복사본(
slice(1))을 만들어 이웃한 요소끼리 쉽게 비교할 수 있도록 합니다. - 두 요소가 같으면 비교를 건너뛰고, 처음으로 다른 값이 나타나는 시점에 오름차순 여부를 확정합니다.
- 이후 요소들이 이미 확정된 방향과 다르게 배치되어 있다면 즉시
'unsorted'를 반환합니다. - 루프가 끝날 때까지
ascending이null이라면 모든 요소가 동일한 것이고, 그렇지 않다면 확정된 방향을 반환합니다.
예제 코드
const arr1 = [7, 2, 1, 3, 2, 1];
const arr2 = [1, 1, 2, 3, 7, 7];
const determineOrder = arr => {
if(arr.length < 2){
return 'not enough items';
};
let ascending = null;
let nextArr = arr.slice(1);
for(var i = 0; i < nextArr.length; i++) {
if(nextArr[i] === arr[i]){
continue;
}else if(ascending === null) {
ascending = nextArr[i] > arr[i];
}else if (ascending !== nextArr[i] > arr[i]){
return 'unsorted';
};
}
if(ascending === null){
return 'all items are equal';
};
return ascending ? 'ascending' : 'descending';
};
console.log(determineOrder(arr1));
console.log(determineOrder(arr2));
console.log(determineOrder([1, 1, 1, 1]));
console.log(determineOrder([7, 2, 2, 1]));실행 결과
코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
unsorted ascending all items are equal descending
결과 해석
[7, 2, 1, 3, 2, 1]→ 중간에 값이 다시 커졌다 작아지므로 unsorted(정렬되지 않음)[1, 1, 2, 3, 7, 7]→ 중복 값이 포함되어도 감소하지 않으므로 ascending(오름차순)[1, 1, 1, 1]→ 모든 값이 동일하므로 all items are equal(모두 같음)[7, 2, 2, 1]→ 중복 값을 허용하며 계속 감소하므로 descending(내림차순)
이처럼 이 함수는 중복 값을 자연스럽게 처리하면서 배열의 정렬 상태를 한 번의 순회(O(n))만으로 판별할 수 있습니다.