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

JavaScript 배열 객체를 uuid 기준으로 그룹화하는 방법

JavaScript로 개발하다 보면 객체 배열 안에서 특정 속성 값이 같은 항목끼리 묶어야 하는 경우가 자주 발생합니다. 이번 글에서는 uuid 속성 값을 기준으로 배열의 객체들을 그룹별로 분류하는 방법을 알아보겠습니다.

문제 상황

다음과 같이 여러 개의 객체를 담고 있는 배열이 있다고 가정해 보겠습니다.

const arr = [
    {"name": "toto", "uuid": 1111},
    {"name": "tata", "uuid": 2222},
    {"name": "titi", "uuid": 1111}
];

여기서 우리가 작성해야 할 함수는 uuid 속성의 값이 서로 같은 객체들끼리 모아, 별도의 배열(배열의 배열) 형태로 분리해 주는 JavaScript 함수입니다.

기대 결과

위 배열을 그룹화하면 최종적으로 다음과 같은 형태의 출력을 얻어야 합니다.

const output = [
    [
        {"name": "toto", "uuid": 1111},
        {"name": "titi", "uuid": 1111}
    ],
    [
        {"name": "tata", "uuid": 2222}
    ]
];

uuid가 1111인 객체 두 개는 하나의 배열로, 2222인 객체 하나는 별도의 배열로 각각 묶인 것을 확인할 수 있습니다.

구현 코드

핵심 아이디어는 해시(객체)를 임시 저장소로 활용하는 것입니다. 각 uuid 값을 키로 사용하고, 해당 키에 대응하는 배열에 객체를 순차적으로 추가합니다. 처음 등장한 키라면 새 배열을 만들어 결과 배열에 함께 참조시켜 주면 됩니다.

const arr = [
    {"name": "toto", "uuid": 1111},
    {"name": "tata", "uuid": 2222},
    {"name": "titi", "uuid": 1111}
];

const groupByElement = arr => {
    const hash = Object.create(null),
    result = [];
    
    arr.forEach(el => {
        if (!hash[el.uuid]) {
            hash[el.uuid] = [];
            result.push(hash[el.uuid]);
        };
        hash[el.uuid].push(el);
    });
    
    return result;
};

console.log(groupByElement(arr));

코드 동작 원리

  • Object.create(null)로 프로토타입이 없는 깨끗한 해시 객체를 생성합니다. 이렇게 하면 toString, hasOwnProperty 같은 내장 키와의 충돌을 방지할 수 있습니다.
  • forEach로 배열을 순회하면서 각 객체의 uuid 값을 확인합니다.
  • 해당 uuid 키가 해시에 없다면 새 배열을 만들고, 이 배열의 참조를 결과 배열(result)에 push합니다.
  • 해시의 해당 키 배열에 현재 객체를 추가합니다. 이미 존재하는 키라면 기존 배열에 바로 추가됩니다.
  • 해시와 결과 배열은 동일한 배열 객체를 공유하기 때문에, 마지막에 result만 반환해도 그룹화된 전체 데이터를 얻을 수 있습니다.

실행 결과

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

[
    [ { name: 'toto', uuid: 1111 }, { name: 'titi', uuid: 1111 } ],
    [ { name: 'tata', uuid: 2222 } ]
]

마무리

이 방식은 배열을 한 번만 순회하므로 시간 복잡도가 O(n)으로 매우 효율적입니다. uuid 외에도 이름, 카테고리, 날짜 등 어떤 속성이든 동일한 패턴으로 그룹화할 수 있으니, 필요에 따라 키로 사용할 속성만 바꿔서 활용해 보시기 바랍니다. 또한 ES2019부터 도입된 Object.groupBy()(또는 Map 기반의 Map.groupBy())를 지원하는 환경이라면 이러한 그룹화 작업을 더욱 간결하게 처리할 수도 있습니다.