JavaScript로 개발을 하다 보면 객체 배열을 특정 조건에 따라 재정렬해야 하는 경우가 자주 발생합니다. 이번 글에서는 flag 속성이 false인 항목들을 배열의 맨 앞으로 옮기되, 전체적인 순서 규칙을 유지하는 정렬 방법을 알아보겠습니다.
문제 상황
다음과 같은 객체 배열이 있다고 가정해 보겠습니다.
const arr = [
{flag: true, other: 1},
{flag: true, other: 2},
{flag: false, other: 3},
{flag: true, other: 4},
{flag: true, other: 5},
{flag: true, other: 6},
{flag: false, other: 7}
];
이 배열을 아래 조건에 따라 정렬하는 JavaScript 함수를 작성해야 합니다.
arr.flag === false인 요소는 배열의 앞쪽에 배치하되, 앞서 등장한 동일 조건의 요소들 뒤에 순서대로 위치해야 합니다.- 조건에 해당하지 않는 요소들은 원래의 상대적 순서를 그대로 유지합니다.
- 요소가 처음 등장한 순서(안정성)가 중요합니다.
따라서 위 배열의 최종 결과는 다음과 같아야 합니다.
const output = [
{flag: false, other: 3},
{flag: false, other: 7},
{flag: true, other: 1},
{flag: true, other: 2},
{flag: true, other: 4},
{flag: true, other: 5},
{flag: true, other: 6}
];
해결 코드
다음은 위 조건을 모두 만족하는 구현 코드입니다.
const arr = [
{flag: true, other: 1},
{flag: true, other: 2},
{flag: false, other: 3},
{flag: true, other: 4},
{flag: true, other: 5},
{flag: true, other: 6},
{flag: false, other: 7}
];
const sortByFlag = arr => {
const sorter = (a, b) => {
if(!a['flag'] && b['flag']){
return -1;
};
if(a['flag'] && !b['flag']){
return 1;
}
return a['other'] - b['other'];
}
arr.sort(sorter);
};
sortByFlag(arr);
console.log(arr);
코드 설명
핵심은 Array.prototype.sort() 메서드에 전달되는 비교 함수입니다. 비교 함수는 두 요소 a와 b를 인자로 받아 다음 규칙에 따라 순서를 결정합니다.
!a['flag'] && b['flag']: a는false, b는true인 경우로, a가 앞에 와야 하므로-1을 반환합니다.a['flag'] && !b['flag']: 반대로 a가true, b가false인 경우로, b가 앞에 와야 하므로1을 반환합니다.- 두 요소의
flag값이 같으면other속성값을 기준으로 오름차순 정렬하여 원래의 순서를 유지합니다.
참고로 ES2019(ES10)부터 JavaScript의 sort()는 안정 정렬(stable sort)을 보장하므로, 비교 결과가 같은 요소들은 원래 배열에서의 상대적 순서가 그대로 유지됩니다.
실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
[
{ flag: false, other: 3 },
{ flag: false, other: 7 },
{ flag: true, other: 1 },
{ flag: true, other: 2 },
{ flag: true, other: 4 },
{ flag: true, other: 5 },
{ flag: true, other: 6 }
]
이처럼 비교 함수 하나만 잘 작성하면 복잡한 조건의 배열 정렬도 간단하고 직관적으로 처리할 수 있습니다.