원본: JavaScript Sort Array – How to Sort an Array Accurately
개발을 하다보면 데이터를 정렬해야 하는 경우가 있습니다. 데이터 정렬 결과가 정확하지 않으면 전체 코드 오작동이나 버그가 발생할 수 있으므로 항상 정확히 정렬해야 합니다.
이번 포스트에서는 자바스크립트에서 배열을 정렬하는 방법을 알아보고, sort() 메소드와 관련된 몇 가지 단점과 보다 정확한 결과를 얻을 수 있는 방법을 살펴보겠습니다.
Table of Contents
sort() 메소드를 사용한 정렬
배열을 정렬하는 가장 쉬운 방법은 비교 함수를 사용하는 것 입니다.
개발자 도구에서 비교 함수를 메소드에 전달하는 다음의 예제를 확인해 보겠습니다:
const numbersArr = [3, 10, 4, 21, 5, 9, 2, 6, 5, 3, 5];
// 오름차순
numbersArr.sort((a, b) => a - b);
console.log(numbersArr);
// 내림차순
numbersArr.sort((a, b) => b - a);
console.log(numbersArr);
sort() 메소드 작동 방식
기본적으로 sort() 메소드는 유니코드 문자 값을 기준으로 배열을 오름차순으로 정렬합니다. 다음 예제를 보겠습니다:
let numArray = [3, 4, 1, 7, 2];
let sortedArr = numArray.sort();
console.log(sortedArr);
중요한 점은 이 메소드를 배열에 적용하면 원본 배열의 위치가 변경된다는 것 입니다. 즉 정렬된 값을 얻기 위해 새로운 배열을 할당할 필요가 없다는 것 입니다.
let numArray = [3, 4, 1, 7, 2];
numArray.sort();
console.log(numArray); // Output: [1,2,3,4,7]
또한 배열 자체에 메소드를 적용할 수도 있습니다.
let numArray = [3, 4, 1, 7, 2].sort();
console.log(numArray); // Output: [1,2,3,4,7]
하지만 정렬 순서를 정하는 콜백함수를 전달하지 않고 그냥 sort() 메소드를 사용하면 자동으로 항목을 유니코드로서 비교를 합니다.
이는 실제로 정렬이 잘못될 수 있음을 의미합니다.
let numArray = [3, 10, 4, 21, 5, 9, 2, 6, 5, 3, 5].sort();
console.log(numArray); // Output: [10,2,21,3,3,4,5,5,5,6,9]
sort() 메소드의 정렬 오류 해결 방법
이제 이 메소드의 단점을 해결하는 방법을 알아보겠습니다.
숫자를 정확히 정렬하는 방법
sort() 메소드는 배열의 요소를 문자열로 변환한 다음 유니코드 순으로 정렬합니다.
다음의 예제를 보면 [10, 5, 80] 배열이 [5, 10, 80]이 아닌 [10, 5, 80]으로 정렬되는 것을 볼 수 있습니다:
let numArr = [10, 5, 80].sort();
console.log(numArr); // Output: [10, 5, 80]
이러한 단점을 해결하기 위해 원하는 순서로 정렬하도록 정의하는 비교 함수를 전달할 수 있습니다.
숫자의 배열을 오름차순으로 정렬하려면 비교 함수의 첫 번째 숫자에서 두 번째 숫자를 빼야합니다.
첫 번째 숫자가 두 번째 숫자보다 작으면 음수를 리턴하고, 크면 양수를, 같으면 0을 리턴합니다.
let numArr = [10, 5, 80];
numArr.sort((a, b) => a - b);
console.log(numArr); // Output: [5, 10, 80]
올바른 정렬 순서를 정의하는 비교 함수를 전달함으로써 배열을 정확하게 정렬할 수 있습니다.
또한 두 번째 숫자에서 첫 번째 숫자를 빼서 배열 요소를 내림차순으로 정렬할 수도 있습니다.
let numArr = [10, 5, 80];
numArr.sort((a, b) => b - a);
console.log(numArr); // Output: [80, 10, 5]
문자열을 정확히 정렬하는 방법
비교 함수를 사용하지 않고 문자열 배열을 정렬할 수도 있지만 특정 상황에서는 정확하지 않을 수 있습니다.
예를 들어 배열 [a, A, b]는 [a, A, b]로 정렬되지 않고 [A, a, b]로 정렬됩니다. A는 소문자 a 보다 유니코드 번호가 작기 때문입니다.
let stringsArr = ["a", "A", "b"].sort();
console.log(stringsArr); // Output: ["A","a","b"]
이러한 현상을 해결하기 위해 정렬 순서를 정의하는 비교 함수를 전달할 수 있습니다.
대소문자를 구분하지 않고 알파벳 순서로 문자열을 정렬하려면 비교 함수에 toLowerCase() 메소드를 사용하면 됩니다.
let stringsArr = ["a", "A", "b"];
stringsArr.sort((a, b) => a.toLowerCase() < b.toLowerCase() ? -1 : 1);
console.log(stringsArr); // Output: ["a", "A", "b"]
원본 배열 보존 방법
또 다른 단점으로는 배열 정렬 시 원본 배열을 변경한다는 점 입니다.
이는 배열의 원래 순서를 유지해야 하거나 큰 배열을 여러 번 정렬해야 하는 경우 문제가 될 수 있습니다.
원본 배열을 수정하지 않으려면 정렬하기 전에 slice() 같은 메소드를 사용하여 배열의 복사본을 만들어 정렬해야 합니다.
let originalArray = [2, 1, 3];
let sortedArray = originalArray.slice().sort((a, b) => a - b);
console.log(originalArray); // Output: [2, 1, 3]
console.log(sortedArray); // Output: [1, 2, 3]
원본 배열과 복사된 배열을 각각 console.log() 메소드를 사용하여 확인하면 원본 배열이 변경되지 않은 것을 확인할 수 있습니다.