실무에서는 다음과 같이 여러 개의 객체를 담고 있는 배열을 자주 다루게 됩니다.
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²)에 가까운 반복 탐색을 피할 수 있어 성능 면에서 유리합니다.