Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript로 2차원 배열의 숫자 그룹화 및 정렬하기

문제 상황

다음과 같은 숫자로 이루어진 2차원 배열이 있다고 가정해 보겠습니다.

const arr = [
    [1, 3, 2],
    [5, 2, 1, 4],
    [2, 1]
];

이 배열에서 같은 숫자끼리 모아 각각 별도의 하위 배열로 묶고, 이렇게 만들어진 하위 배열들을 오름차순으로 정렬하는 JavaScript 함수를 작성해야 합니다.

즉, 최종 결과물은 다음과 같은 형태가 되어야 합니다.

const output = [
    [1, 1, 1],
    [2, 2, 2],
    [3],
    [4],
    [5]
];

해결 방법

이 문제는 객체(맵)를 활용하면 효율적으로 해결할 수 있습니다. 각 숫자가 처음 등장할 때 새로운 빈 배열을 생성하고 결과 배열에 추가한 뒤, 이후 동일한 숫자가 나올 때마다 해당 배열에 값을 쌓아가는 방식입니다.

핵심 로직은 다음과 같습니다.

  • 숫자를 키로 사용하는 맵(map)을 만들어 중복 확인과 접근을 O(1) 시간 복잡도로 처리합니다.
  • 배열을 한 번 순회하며 각 요소를 맵의 해당 그룹에 추가합니다.
  • 모든 요소 처리 후, 결과 배열을 각 그룹의 첫 번째 값을 기준으로 오름차순 정렬합니다.

구현 코드

전체 코드는 다음과 같습니다.

const arr = [
    [1, 3, 2],
    [5, 2, 1, 4],
    [2, 1]
];

const groupAndSort = arr => {
    const res = [];
    const map = Object.create(null);

    Array.prototype.forEach.call(arr, item => {
        item.forEach(el => {
            if (!(el in map)) {
                map[el] = [];
                res.push(map[el]);
            }
            map[el].push(el);
        });
    });

    res.sort((a, b) => {
        return a[0] - b[0];
    });

    return res;
};

console.log(groupAndSort(arr));

코드 설명

  1. map 생성: Object.create(null)을 사용해 프로토타입이 없는 순수 객체를 만들면, toString이나 hasOwnProperty 같은 내장 속성 이름과의 충돌을 걱정할 필요가 없습니다.
  2. 그룹화: 각 숫자가 처음 나타나면 새 배열을 만들어 res에 참조로 저장하고, 이후에는 해당 배열에 계속 값을 push합니다.
  3. 정렬: 마지막에 각 그룹의 첫 번째 요소(a[0])를 비교하여 오름차순으로 정렬합니다. 같은 그룹 내부의 값은 이미 삽입 순서대로 동일하기 때문에 별도 정렬이 필요하지 않습니다.

실행 결과

코드를 실행하면 콘솔에 다음과 같은 출력이 나타납니다.

[ [ 1, 1, 1 ], [ 2, 2, 2 ], [ 3 ], [ 4 ], [ 5 ] ]

시간 복잡도는 전체 요소 수를 N이라 할 때 O(N log N)이며, 대부분의 비용은 최종 정렬 단계에서 발생합니다. 그룹화 자체는 선형 시간에 처리되므로, 데이터 크기가 커져도 안정적으로 동작하는 효율적인 방식입니다.