문제 상황
다음과 같이 위치(location)와 신분(identity_long) 정보를 담고 있는 객체 배열이 있다고 가정해 보겠습니다.
const arr = [
{"location":"Kirrawee","identity_long":"student"},
{"location":"Kirrawee","identity_long":"visitor"},
{"location":"Kirrawee","identity_long":"visitor"},
{"location":"Kirrawee","identity_long":"worker"},
{"location":"Sutherland","identity_long":"student"},
{"location":"Sutherland","identity_long":"resident"},
{"location":"Sutherland","identity_long":"worker"},
{"location":"Sutherland","identity_long":"resident"},
{"location":"Miranda","identity_long":"resident"},
{"location":"Miranda","identity_long":"worker"},
{"location":"Miranda","identity_long":"student"},
{"location":"Miranda","identity_long":""},
{"location":"Miranda","identity_long":"worker"},
{"location":"Miranda","identity_long":"resident"}
];우리가 작성해야 할 JavaScript 함수는 위와 같은 객체 배열을 입력받아, 동일한 객체들을 location 속성을 기준으로 하나로 묶은 새로운 배열을 만들어야 합니다.
동시에 각 객체에는 해당 조합이 원본 배열에 몇 번 등장했는지를 나타내는 count 속성이 부여되어야 합니다.
따라서 위 배열에 대한 최종 결과물은 다음과 같은 형태가 됩니다.
const output = [
{"location":"Kirrawee","identity":"student","count":1},
{"location":"Kirrawee","identity":"visitor","count":2},
{"location":"Kirrawee","identity":"worker","count":1},
{"location":"Sutherland","identity":"student","count":1},
{"location":"Sutherland","identity":"resident","count":2},
{"location":"Sutherland","identity":"worker","count":1},
{"location":"Miranda","identity":"resident","count":2},
{"location":"Miranda","identity":"worker","count":2},
{"location":"Miranda","identity":"student","count":1}
];구현 코드
이 문제는 Map 객체를 활용하면 깔끔하게 해결할 수 있습니다. 핵심 아이디어는 각 객체를 JSON.stringify()로 문자열화하여 고유한 키로 사용하고, 이미 존재하는 키라면 count 값을 1씩 증가시키는 것입니다.
const arr = [
{"location":"Kirrawee","identity_long":"student"},
{"location":"Kirrawee","identity_long":"visitor"},
{"location":"Kirrawee","identity_long":"visitor"},
{"location":"Kirrawee","identity_long":"worker"},
{"location":"Sutherland","identity_long":"student"},
{"location":"Sutherland","identity_long":"resident"},
{"location":"Sutherland","identity_long":"worker"},
{"location":"Sutherland","identity_long":"resident"},
{"location":"Miranda","identity_long":"resident"},
{"location":"Miranda","identity_long":"worker"},
{"location":"Miranda","identity_long":"student"},
{"location":"Miranda","identity_long":""},
{"location":"Miranda","identity_long":"worker"},
{"location":"Miranda","identity_long":"resident"}
];
const groupArray = (arr = []) => {
// Map 생성
let map = new Map()
for (let i = 0; i < arr.length; i++) {
const s = JSON.stringify(arr[i]);
if (!map.has(s)) {
map.set(s, {
location: arr[i].location,
identity: arr[i].identity_long,
count: 1,
});
} else {
map.get(s).count++;
}
}
const res = Array.from(map.values())
return res;
};
console.log(groupArray(arr));실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
[
{ location: 'Kirrawee', identity: 'student', count: 1 },
{ location: 'Kirrawee', identity: 'visitor', count: 2 },
{ location: 'Kirrawee', identity: 'worker', count: 1 },
{ location: 'Sutherland', identity: 'student', count: 1 },
{ location: 'Sutherland', identity: 'resident', count: 2 },
{ location: 'Sutherland', identity: 'worker', count: 1 },
{ location: 'Miranda', identity: 'resident', count: 2 },
{ location: 'Miranda', identity: 'worker', count: 2 },
{ location: 'Miranda', identity: 'student', count: 1 },
{ location: 'Miranda', identity: '', count: 1 }
]핵심 포인트 정리
- JSON.stringify()로 직렬화: 객체는 참조 타입이기 때문에 Map의 키로 직접 사용할 수 없습니다. 문자열로 변환하면 내용 기반 비교가 가능해져 동일한 객체를 정확히 판별할 수 있습니다.
- Map의 순서 보장: Map은 키의 삽입 순서를 유지하므로, 결과 배열 역시 각 조합이 원본 배열에서 처음 등장한 순서를 그대로 따르게 됩니다.
- 빈 값도 하나의 그룹: identity_long이 빈 문자열("")인 객체도 별개의 그룹으로 집계됩니다. 빈 값을 제외하고 싶다면 반복문 안에서 조건 분기를 추가하면 됩니다.
- 시간 복잡도: Map 조회와 삽입은 평균 O(1)이므로 전체 알고리즘의 시간 복잡도는 O(n)으로, 대량의 데이터에서도 효율적으로 동작합니다.