문제 소개
다음과 같이 숫자로 구성된 세 개의 JavaScript 배열이 있다고 가정해 보겠습니다.
const array1 = [10,23,53,74,33,56,6,0,43,45,11]; const array2 = [52,46,27,28,4,11,53,6,75,75,22]; const array3 = [26,18,10,12,31,12,5,8,44,34,65];
모든 배열의 길이는 항상 동일하며, 배열의 개수는 몇 개가 되더라도 상관없습니다.
이제 우리가 작성해야 할 함수는 여러 개의 배열을 입력받아, 같은 인덱스 위치에 있는 요소들을 서로 비교한 후 각 값의 순위(내림차순 기준)를 새로운 배열로 매핑하는 것입니다.
쉽게 말해, 첫 번째 인덱스에서는 세 배열의 첫 번째 요소끼리 비교해 가장 큰 값에 1위, 그다음 값에 2위, 가장 작은 값에 3위를 부여하고, 이 과정을 나머지 모든 인덱스에 대해 반복하는 방식입니다.
따라서 위 배열들에 대한 기대 출력은 다음과 같습니다.
const array1 = [3,2,1,1,1,1,2,3,2,2,3]; const array2 = [1,1,2,2,2,2,1,2,1,1,2]; const array3 = [2,3,3,3,3,3,3,1,2,3,1];
구현 코드
다음은 이 문제를 해결하는 전체 코드입니다.
const array1 = [10,23,53,74,33,56,6,0,43,45,11];
const array2 = [52,46,27,28,4,11,53,6,75,75,22];
const array3 = [26,18,10,12,31,12,5,8,44,34,65];
// 여러 배열을 인덱스별로 묶어주는 전치(transpose) 헬퍼 함수
const transpose = (rank, arr) => {
return arr.map((el, ind) => {
return [...(rank[ind] || []), el];
});
};
// 각 그룹(같은 인덱스의 값 모음)에 대해 내림차순 순위를 계산하는 함수
const ranks = arr => {
return arr.map(
Map.prototype.get,
[...arr]
.sort((a, b) => b - a)
.reduce((r => (m, v) => m.set(v, (r++, m.get(v)) || r))(0), new Map)
);
};
// 순위 계산 후 결과를 원래 배열 구조로 복원하는 메인 함수
const findRanks = (...arrs) => {
return arrs
.reduce(transpose, [])
.map(ranks)
.reduce(transpose, []);
};
console.log(findRanks(array1, array2, array3));
코드 동작 원리
핵심 로직은 크게 세 단계로 구성됩니다.
1단계 − 전치(Transpose): reduce와 map을 활용해 여러 배열을 인덱스별로 재배열합니다. 예를 들어 첫 번째 그룹은 [10, 52, 26]처럼 같은 위치의 값들이 하나로 묶입니다.
2단계 − 순위 계산(Ranks): 각 그룹의 값을 내림차순으로 정렬한 뒤 Map 객체에 '값 → 순위' 형태로 저장하고, 원본 값에 대응하는 순위를 반환합니다. 값이 같으면 동일한 순위를 공유합니다.
3단계 − 재전치: 계산이 끝난 순위들을 다시 transpose를 통해 원래의 배열 구조로 되돌려 최종 결과를 완성합니다.
실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
[ [ 3, 2, 1, 1, 1, 1, 2, 3, 3, 2, 3 ], [ 1, 1, 2, 2, 3, 3, 1, 2, 1, 1, 2 ], [ 2, 3, 3, 3, 2, 2, 3, 1, 2, 3, 1 ] ]