JavaScript 개발을 하다 보면 하나의 배열을 다른 배열에 담긴 값들을 기준으로 정렬해야 하는 경우가 종종 있습니다. 예를 들어, 특정 요소들을 배열의 맨 앞으로 끌어올리고 나머지 요소들은 기존 순서를 그대로 유지하고 싶은 상황이 그렇습니다.
문제 상황
다음과 같이 원본 배열과 정렬 기준이 될 배열이 있다고 가정해 보겠습니다.
const originalArray = ['Apple', 'Cat', 'Fan', 'Goat', 'Van', 'Zebra']; const sortOrder = ['Zebra', 'Van'];
여기서 우리가 원하는 결과는 sortOrder 배열에 포함된 요소들('Zebra', 'Van')이 원본 배열의 가장 앞쪽에 배치되고, 나머지 요소들은 원래의 순서를 유지하는 것입니다.
해결 방법: 커스텀 비교 함수 활용
배열의 sort() 메서드는 비교 함수(comparator)를 인자로 받을 수 있습니다. 이 비교 함수 안에서 각 요소가 sortOrder 배열에 포함되어 있는지 includes()로 확인하면 원하는 정렬을 손쉽게 구현할 수 있습니다.
const originalArray = ['Apple', 'Cat', 'Fan', 'Goat', 'Van', 'Zebra'];
const sortOrder = ['Zebra', 'Van'];
const sorter = (a, b) => {
if (sortOrder.includes(a)) {
return -1;
}
if (sortOrder.includes(b)) {
return 1;
}
return 0;
};
originalArray.sort(sorter);
console.log(originalArray);동작 원리
return -1: 첫 번째 요소a가sortOrder에 포함되어 있다면,a를 두 번째 요소b보다 앞에 위치시킵니다.return 1: 두 번째 요소b가sortOrder에 포함되어 있다면,b를a보다 앞에 위치시킵니다.return 0: 두 요소 모두sortOrder에 없다면 순서를 변경하지 않고 기존 순서를 유지합니다.
실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
[ 'Zebra', 'Van', 'Apple', 'Cat', 'Fan', 'Goat' ]
결과를 보면 sortOrder에 있던 'Zebra'와 'Van'이 배열의 맨 앞으로 이동했고, 나머지 요소들('Apple', 'Cat', 'Fan', 'Goat')은 원래 순서를 그대로 유지하고 있는 것을 확인할 수 있습니다.
참고: 우선순위까지 반영하고 싶다면?
만약 sortOrder 배열 내부의 순서까지 그대로 반영하고 싶다면 indexOf()를 활용한 방법도 유용합니다.
const sorter = (a, b) => {
const indexA = sortOrder.indexOf(a);
const indexB = sortOrder.indexOf(b);
if (indexA === -1 && indexB === -1) return 0;
if (indexA === -1) return 1;
if (indexB === -1) return -1;
return indexA - indexB;
};이 방식은 sortOrder에 있는 요소들끼리도 지정된 순서대로 정렬되므로, 우선순위가 중요한 로직에서 더욱 안정적인 결과를 보장합니다.