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

JavaScript에서 중첩 배열의 길이를 기준으로 객체 배열 정렬하기

JavaScript로 개발을 하다 보면 객체 배열 안에 또 다른 배열이 중첩되어 있는 데이터 구조를 자주 만나게 됩니다. 이번 글에서는 각 객체가 가진 중첩 배열의 길이(요소 개수)를 기준으로 배열을 내림차순으로 정렬하는 방법을 알아보겠습니다.

문제 상황

다음과 같이 각 객체가 elements라는 중첩 배열 속성을 포함하는 배열이 있다고 가정해 봅시다.

const arr = [
    { name: "Cat1", elements: [
        { name: name, id: id }
    ]},
    { name: "Cat2", elements: [
        { name: name, id: id },
        { name: name, id: id },
        { name: name, id: id }
    ]},
    { name: "Cat3", elements: [
        { name: name, id: id },
        { name: name, id: id }
    ]}
];

여기서 요구 사항은 이 배열을 받아서 정렬하는 JavaScript 함수를 작성하는 것입니다. 정렬 기준은 다음과 같습니다.

  • elements 배열에 포함된 요소가 많은 객체일수록 더 앞쪽에 위치해야 합니다.
  • 즉, 중첩 배열의 길이를 기준으로 내림차순 정렬을 수행합니다.

따라서 정렬이 완료된 후 배열은 다음과 같은 순서가 되어야 합니다.

const output = [
    { name: "Cat2", elements: [ /* 요소 3개 */ ] },
    { name: "Cat3", elements: [ /* 요소 2개 */ ] },
    { name: "Cat1", elements: [ /* 요소 1개 */ ] }
];

해결 방법: sort()와 비교 함수 활용

JavaScript의 Array.prototype.sort() 메서드는 비교 함수(comparator)를 인자로 받습니다. 비교 함수는 두 요소 a와 b를 비교하여 음수를 반환하면 a가 앞으로, 양수를 반환하면 b가 앞으로 오도록 정렬합니다. 이 원리를 활용하면 아주 간단하게 해결할 수 있습니다.

예제 코드

const arr = [
    { "name": "Cat1", elements: [
        { "name": "name", "id": "id" }
    ]},
    { "name": "Cat2", elements: [
        { "name": "name", "id": "id" },
        { "name": "name", "id": "id" },
        { "name": "name", "id": "id" }
    ]},
    { "name": "Cat3", elements: [
        { "name": "name", "id": "id" },
        { "name": "name", "id": "id" }
    ]}
];

const sorter = (a, b) => {
    if (a.elements.length > b.elements.length) {
        return -1;
    } else {
        return 1;
    }
};

arr.sort(sorter);
console.log(JSON.stringify(arr, undefined, 4));

더 간결한 표현식

위의 비교 함수는 산술 연산을 사용해 한 줄로 더 간결하게 작성할 수도 있습니다.

arr.sort((a, b) => b.elements.length - a.elements.length);

b의 길이에서 a의 길이를 빼면, a가 더 클 때 음수가 반환되어 a가 앞으로 정렬됩니다. 결과는 동일하며 코드가 훨씬 짧아집니다.

실행 결과

콘솔에 출력되는 결과는 다음과 같습니다.

[
    {
        "name": "Cat2",
        "elements": [
            { "name": "name", "id": "id" },
            { "name": "name", "id": "id" },
            { "name": "name", "id": "id" }
        ]
    },
    {
        "name": "Cat3",
        "elements": [
            { "name": "name", "id": "id" },
            { "name": "name", "id": "id" }
        ]
    },
    {
        "name": "Cat1",
        "elements": [
            { "name": "name", "id": "id" }
        ]
    }
]

정리 및 주의사항

  • sort() 메서드는 원본 배열을 직접 변경(mutate)합니다. 원본을 유지해야 한다면 먼저 스프레드 연산자나 toSorted()(ES2023)를 사용해 복사본을 만든 후 정렬하세요.
  • 중첩 배열이 존재하지 않는 객체가 섞여 있을 수 있다면 (a.elements?.length || 0)처럼 옵셔널 체이닝으로 안전하게 처리하는 것이 좋습니다.
  • 오름차순 정렬이 필요하다면 비교 순서만 반대로 바꾸면 됩니다.

이처럼 sort()의 비교 함수만 잘 활용하면 중첩 배열의 길이뿐 아니라 객체의 어떤 속성 기준으로도 자유롭게 정렬할 수 있습니다.