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

JavaScript에서 객체 배열 집계하기 – reduce()로 이름별 합계 구하기

JavaScript를 다루다 보면 객체 배열 안에 흩어져 있는 데이터를 특정 기준으로 묶어서 집계해야 하는 경우가 자주 발생합니다. 이번 글에서는 여러 사람의 거래 내역이 담긴 배열을 사람별로 그룹화하여 금액 합계를 구하는 방법을 reduce() 메서드를 활용해 알아보겠습니다.

예를 들어, 다음과 같이 여러 사람의 거래 정보가 담긴 객체 배열이 있다고 가정해 보겠습니다.

const transactions = [{
    name: 'Rakesh',
    amount: 1500
}, {
    name: 'Rajesh',
    amount: 1200
}, {
    name: 'Ramesh',
    amount: 1750
}, {
    name: 'Rakesh',
    amount: 2100
}, {
    name: 'Mukesh',
    amount: 1100
}, {
    name: 'Rajesh',
    amount: 1950
}, {
    name: 'Mukesh',
    amount: 1235
}, {
    name: 'Ramesh',
    amount: 2000
}];

여기서 우리가 작성해야 할 함수는 이 배열을 입력받아, 동일한 사람의 거래 금액을 하나의 객체로 묶어 집계한 결과를 반환하는 함수입니다. 즉, 같은 이름을 가진 레코드들의 amount 값을 모두 더해서 각 사람당 하나의 객체만 남기는 것이 목표입니다.

구현 예제

reduce()를 사용하면 배열을 순회하면서 누적 결과(accumulator)에 데이터를 쌓아갈 수 있습니다. 누적 배열에서 이미 해당 이름의 객체가 존재하는지 findIndex()로 확인하고, 존재하면 금액을 더하고, 없으면 새로운 객체를 추가하는 방식으로 구현할 수 있습니다.

const transactions = [{
    name: 'Rakesh',
    amount: 1500
}, {
    name: 'Rajesh',
    amount: 1200
}, {
    name: 'Ramesh',
    amount: 1750
}, {
    name: 'Rakesh',
    amount: 2100
}, {
    name: 'Mukesh',
    amount: 1100
}, {
    name: 'Rajesh',
    amount: 1950
}, {
    name: 'Mukesh',
    amount: 1235
}, {
    name: 'Ramesh',
    amount: 2000
}];
const aggregateArray = arr => {
    return arr.reduce((acc, val) => {
        const index = acc.findIndex(obj => obj.name === val.name);
        if(index !== -1){
            acc[index].amount += val.amount;
        }else{
            acc.push({
                name: val.name,
                amount: val.amount
            });
        };
        return acc;
    }, []);
};
console.log(aggregateArray(transactions));

코드 설명

위 코드의 핵심 로직은 다음과 같습니다.

1. 초기값으로 빈 배열 설정
reduce()의 두 번째 인자로 빈 배열 []을 전달하여, 누적 결과가 처음에는 아무것도 없는 상태에서 시작되도록 합니다.

2. 기존 항목 검색
findIndex()를 통해 누적 배열 안에 현재 처리 중인 거래와 같은 이름을 가진 객체가 있는지 확인합니다. 같은 이름이 없다면 -1이 반환됩니다.

3. 조건 분기 처리
이미 존재하는 이름이라면 해당 객체의 amount에 현재 금액을 더하고, 존재하지 않는다면 새 객체를 누적 배열에 추가(push)합니다.

출력 결과

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

[
    { name: 'Rakesh', amount: 3600 },
    { name: 'Rajesh', amount: 3150 },
    { name: 'Ramesh', amount: 3750 },
    { name: 'Mukesh', amount: 2335 }
]

결과를 보면 중복된 이름의 거래 금액이 모두 합산되어, 각 사람별로 하나의 집계 객체만 남은 것을 확인할 수 있습니다.

성능 개선 팁

위 방식은 직관적이지만, findIndex()가 매번 배열을 처음부터 탐색하기 때문에 데이터가 많아지면 시간 복잡도가 O(n²)까지 늘어날 수 있습니다. 대량의 데이터를 다룰 때는 임시 객체(Map 또는 일반 객체)를 키-값 저장소로 활용하면 O(n) 성능으로 개선할 수 있습니다.