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

JavaScript에서 동일한 키 값을 가진 객체 병합 및 개수 계산하기

실무에서는 다음과 같이 동일한 데이터가 여러 번 중복되어 포함된 객체 배열을 자주 다루게 됩니다.

const arr = [{
    "value": 10,
    "id": "111",
    "name": "BlackCat",
}, {
    "value": 10,
    "id": "111",
    "name": "BlackCat",
}, {
    "value": 15,
    "id": "777",
    "name": "WhiteCat",
}];

이 배열을 인자로 받아, "id" 속성의 값이 서로 같은 객체들을 하나로 병합하는 JavaScript 함수를 작성해야 합니다. 병합할 때는 해당 id가 몇 번 등장했는지를 나타내는 count 속성도 함께 추가합니다.

따라서 위 배열에 함수를 적용하면 결과는 다음과 같아야 합니다.

const output = [{
    "value": 10,
    "id": "111",
    "name": "BlackCat",
    "count": 2,
}, {
    "value": 15,
    "id": "777",
    "name": "WhiteCat",
    "count": 1,
}]

구현 예제

const arr = [{
    "value": 10,
    "id": "111",
    "name": "BlackCat",
}, {
    "value": 10,
    "id": "111",
    "name": "BlackCat",
}, {
    "value": 15,
    "id": "777",
    "name": "WhiteCat",
}];
const combinedItems = (arr = []) => {
    const res = arr.reduce((acc, obj) => {
        let found = false;
        for (let i = 0; i < acc.length; i++) {
            if (acc[i].id === obj.id) {
                found = true;
                acc[i].count++;
            };
        }
        if (!found) {
            obj.count = 1;
            acc.push(obj);
        }
        return acc;
    }, []);
    return res;
}
console.log(combinedItems(arr));

코드 설명

  • reduce() 메서드를 사용해 배열을 순회하면서 결과를 담을 누적 배열 acc를 만듭니다.
  • 각 객체에 대해 누적 배열 안에 같은 id를 가진 항목이 이미 존재하는지 확인합니다.
  • 같은 id가 존재하면 found 플래그를 true로 바꾸고 해당 항목의 count를 1 증가시킵니다.
  • 같은 id가 없다면 새 객체의 count를 1로 초기화한 뒤 누적 배열에 추가합니다.

출력 결과

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

[
    { value: 10, id: '111', name: 'BlackCat', count: 2 },
    { value: 15, id: '777', name: 'WhiteCat', count: 1 }
]

참고: 성능 개선 팁

위 방식은 매번 내부 반복문으로 기존 항목을 검색하기 때문에 시간 복잡도가 O(n²)입니다. 데이터 양이 많다면 Map 객체를 활용해 O(n)으로 최적화할 수 있습니다.

const combinedItems = (arr = []) => {
    const map = new Map();
    arr.forEach(obj => {
        if (map.has(obj.id)) {
            map.get(obj.id).count++;
        } else {
            map.set(obj.id, { ...obj, count: 1 });
        }
    });
    return [...map.values()];
};

Map은 키 조회가 상수 시간에 이루어지므로 대용량 데이터에서도 빠르게 동작하며, 마지막에 [...map.values()]로 배열 형태의 결과를 손쉽게 얻을 수 있습니다.