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

JavaScript – 반복되는 키를 가진 배열 값 합산하기

실무에서는 다음과 같이 여러 개의 객체를 담고 있는 배열을 자주 다루게 됩니다.

const arr = [
    {'ID-01':1},
    {'ID-02':3},
    {'ID-01':3},
    {'ID-02':5}
];

이때 요구 사항은 동일한 키를 가진 객체들의 값을 하나로 합산하는 것입니다. 즉, 같은 ID끼리 묶어서 각각의 합계를 구해야 합니다.

따라서 위 배열에 대한 최종 출력 결과는 다음과 같아야 합니다.

const output = [{'ID-01':4}, {'ID-02':8}];

접근 방법

배열을 처음부터 끝까지 순회하면서, 각 객체의 키가 이미 결과 배열에 존재하는지 확인합니다. 키가 존재하면 기존 객체의 값에 현재 값을 더하고, 존재하지 않으면 새로운 객체를 결과 배열에 추가하는 방식으로 문제를 해결할 수 있습니다.

예제 코드

다음은 전체 코드입니다.

const arr = [
    {'ID-01':1},
    {'ID-02':3},
    {'ID-01':3},
    {'ID-02':5}
];

// 결과 배열에서 특정 키를 가진 객체의 인덱스를 찾는 헬퍼 함수
const findKeyIndex = (res, key) =>
    res.findIndex(el => typeof el[key] === 'number');

const groupArray = arr => {
    const res = [];
    for (let i = 0; i < arr.length; i++) {
        // 각 객체의 첫 번째 키를 추출
        const key = Object.keys(arr[i])[0];
        const ind = findKeyIndex(res, key);
        if (ind !== -1) {
            // 동일한 키가 이미 존재하면 기존 값에 합산
            res[ind][key] += arr[i][key];
        } else {
            // 존재하지 않으면 새 객체를 추가
            res.push({ ...arr[i] });
        }
    }
    return res;
};

console.log(groupArray(arr));

코드 설명

  • Object.keys(arr[i])[0] : 각 객체의 첫 번째 키를 추출합니다.
  • findIndex() : 결과 배열에서 동일한 키를 가진 객체의 위치를 찾습니다.
  • 키가 이미 존재하면(ind !== -1) 기존 값에 더하고, 그렇지 않으면 새 객체를 배열에 추가합니다.
  • 원본 배열을 보존하기 위해 { ...arr[i] }로 얕은 복사본을 추가하는 것이 안전합니다.

출력 결과

위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.

[ { 'ID-01': 4 }, { 'ID-02': 8 } ]

대안: reduce()를 활용한 방법

조금 더 함수형 스타일로 작성하고 싶다면 reduce()와 임시 객체(맵)를 활용할 수도 있습니다. 이 방식은 키 조회 속도가 빠르고 코드도 간결합니다.

const groupArray = arr => {
    const map = {};
    arr.forEach(obj => {
        const key = Object.keys(obj)[0];
        map[key] = (map[key] || 0) + obj[key];
    });
    return Object.keys(map).map(key => ({ [key]: map[key] }));
};

console.log(groupArray(arr));
// [ { 'ID-01': 4 }, { 'ID-02': 8 } ]

두 방법 모두 동일한 결과를 반환하지만, 데이터 양이 많다면 객체 맵을 사용하는 reduce() 방식이 O(n²)에 가까운 반복 탐색을 피할 수 있어 성능 면에서 유리합니다.