JavaScript로 작업하다 보면 하나의 배열에 담긴 순서 정보를 기준으로 다른 배열을 재정렬해야 하는 경우가 종종 있습니다. 예를 들어, 키 순서를 담은 배열과 실제 데이터 객체 배열이 따로 존재하는 상황이 대표적입니다.
문제 상황
다음과 같이 두 개의 배열이 있다고 가정해 보겠습니다.
const arr1 = ['d','a','b','c'];
const arr2 = [{a:1},{c:3},{d:4},{b:2}];여기서 우리가 작성해야 할 함수는 이 두 배열을 인자로 받아, 첫 번째 배열(arr1)의 요소 순서에 따라 두 번째 배열(arr2)을 정렬하는 것입니다. 즉, 두 번째 배열에 있는 각 객체의 키(key)를 첫 번째 배열의 요소 순서에 맞춰 배치해야 합니다.
따라서 기대되는 출력 결과는 다음과 같습니다.
const output = [{d:4},{a:1},{b:2},{c:3}];해결 방법: sort()와 indexOf() 활용
핵심 아이디어는 간단합니다. 각 객체에서 첫 번째 키를 추출한 뒤, 해당 키가 arr1에서 몇 번째 위치에 있는지 비교하여 정렬 기준으로 삼는 것입니다.
예제 코드
const arr1 = ['d','a','b','c'];
const arr2 = [{a:1},{c:3},{d:4},{b:2}];
const sortArray = (arr1, arr2) => {
arr2.sort((a, b) => {
const aKey = Object.keys(a)[0];
const bKey = Object.keys(b)[0];
return arr1.indexOf(aKey) - arr1.indexOf(bKey);
});
};
sortArray(arr1, arr2);
console.log(arr2);코드 동작 원리
위 코드가 어떻게 동작하는지 단계별로 살펴보겠습니다.
1. 키 추출: Object.keys(a)[0]를 사용해 각 객체의 첫 번째 키를 가져옵니다. 예를 들어 {d:4}라면 'd'가 됩니다.
2. 순서 비교: arr1.indexOf()로 각 키가 참조 배열에서 몇 번째 인덱스에 위치하는지 확인합니다.
3. 정렬 수행: 두 인덱스 값의 차이를 반환함으로써, arr1의 순서('d' → 'a' → 'b' → 'c') 그대로 arr2가 정렬됩니다.
실행 결과
콘솔에 출력되는 결과는 다음과 같습니다.
[ { d: 4 }, { a: 1 }, { b: 2 }, { c: 3 } ]첫 번째 배열의 순서인 d, a, b, c와 정확히 일치하는 것을 확인할 수 있습니다.
성능 개선 팁
배열의 크기가 클 경우 indexOf()는 매 비교마다 선형 탐색(O(n))을 수행하므로 비효율적일 수 있습니다. 이럴 때는 미리 Map 객체에 키-인덱스 매핑을 만들어 두면 O(1) 조회가 가능해 성능이 크게 향상됩니다.
const sortArrayOptimized = (order, items) => {
const orderMap = new Map(order.map((key, index) => [key, index]));
items.sort((a, b) => {
const aKey = Object.keys(a)[0];
const bKey = Object.keys(b)[0];
return orderMap.get(aKey) - orderMap.get(bKey);
});
};데이터 양이 많거나 정렬 로직이 자주 호출되는 환경이라면 이 최적화 버전을 사용하는 것이 좋습니다.