Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript에서 숫자와 영숫자가 섞인 배열을 자연스럽게 정렬하는 방법

실무에서는 숫자만 있는 문자열과 알파벳·숫자가 조합된 문자열이 하나의 배열에 섞여 있는 경우를 종종 마주하게 됩니다. 이런 배열을 단순히 sort() 메서드로 정렬하면 사전순(lexicographic)으로 처리되어 'A10'이 'A3'보다 앞에 오는 등 의도와 다른 결과가 나옵니다. 예를 들어 다음과 같은 배열이 있다고 가정해 보겠습니다.

const arr = ['A1', 'A10', 'A11', 'A12', 'A3A', 'A3B', 'A3', 'A4', 'B10', 'B2', 'F1', '1', '2', 'F3'];

우리는 이 배열을 유일한 인자로 받아 다음 규칙에 따라 제자리(in-place)에서 정렬하는 JavaScript 함수를 작성해야 합니다.

  • 숫자만 포함된 문자열은 가장 앞에 위치하며, 오름차순으로 정렬됩니다.
  • 알파벳과 숫자가 결합된 문자열은 먼저 알파벳 순서대로, 그다음에는 숫자 크기순(오름차순)으로 정렬됩니다.

따라서 최종 출력 결과는 다음과 같아야 합니다.

const output = ['1', '2', 'A1', 'A3', 'A3A', 'A3B', 'A4', 'A10', 'A11', 'A12', 'B2', 'B10', 'F1', 'F3'];

정렬 함수 구현 예제

아래 코드는 문자열을 숫자 조각과 비숫자 조각으로 분리한 뒤, 조각 단위로 비교하여 위 규칙을 그대로 구현한 것입니다.

const arr = ['A1', 'A10', 'A11', 'A12', 'A3A', 'A3B', 'A3', 'A4', 'B10', 'B2', 'F1', '1', '2', 'F3'];
const alphaNumericSort = (arr = []) => {
   const sorter = (a, b) => {
      const isNumber = (v) => (+v).toString() === v;
      const aPart = a.match(/\d+|\D+/g);
      const bPart = b.match(/\d+|\D+/g);
      let i = 0;
      let len = Math.min(aPart.length, bPart.length);
      while (i < len && aPart[i] === bPart[i]) {
         i++;
      }
      if (i === len) {
         return aPart.length - bPart.length;
      }
      if (isNumber(aPart[i]) && isNumber(bPart[i])) {
         return aPart[i] - bPart[i];
      }
      return aPart[i].localeCompare(bPart[i]);
   };
   arr.sort(sorter);
};
alphaNumericSort(arr);
console.log(arr);

실행 결과

위 코드를 실행하면 콘솔에 다음과 같이 출력됩니다.

[
   '1', '2', 'A1',
   'A3', 'A3A', 'A3B',
   'A4', 'A10', 'A11',
   'A12', 'B2', 'B10',
   'F1', 'F3'
]

코드 동작 원리

핵심 로직을 단계별로 살펴보면 다음과 같습니다.

  • isNumber(v): (+v).toString() === v 비교를 통해 해당 조각이 순수한 숫자 문자열인지 판별합니다.
  • match(/\d+|\D+/g): 각 문자열을 연속된 숫자 조각과 비숫자 조각으로 분할합니다. 예를 들어 'A10'은 ['A', '10']으로 나뉩니다.
  • 조각별 비교: 두 문자열의 조각을 앞에서부터 하나씩 비교하다가 처음으로 달라지는 지점에서, 양쪽 모두 숫자라면 수치로 비교하고 그렇지 않으면 localeCompare()로 사전순 비교를 수행합니다.
  • 길이 비교: 한쪽이 다른 쪽의 접두어처럼 모든 조각이 일치하는 경우, 조각 개수의 차이를 반환해 더 짧은 문자열을 앞에 배치합니다.

이 방식을 활용하면 일반적인 사전순 정렬에서 'A10'이 'A9'보다 앞에 오는 문제를 피할 수 있으며, 사람이 직관적으로 기대하는 자연스러운(natural) 순서대로 배열을 정렬할 수 있습니다.