문제 소개
실무에서는 여러 사람의 정보가 하나의 객체에 몰려 있는 경우가 종종 있습니다. 다음과 같은 객체를 살펴보겠습니다.
const obj = {
"Person1_Age": 22,
"Person1_Height": 170,
"Person1_Weight": 72,
"Person2_Age": 27,
"Person2_Height": 160,
"Person2_Weight": 56
};키 이름을 보면 Person1_, Person2_처럼 언더스코어(_) 앞의 접두사로 사람을 구분할 수 있습니다. 이번 글에서는 이런 객체를 받아 각 사람별로 데이터를 독립적인 객체로 분리한 뒤, 배열로 묶어 반환하는 함수를 작성해 보겠습니다.
기대 결과
위 객체를 변환하면 최종적으로 다음과 같은 구조의 배열이 나와야 합니다.
const output = [
{
"name": "Person1",
"age": 22,
"height": 170,
"weight": 72
},
{
"name": "Person2",
"age": 27,
"height": 160,
"weight": 56
}
];해결 방법
핵심 아이디어는 다음과 같습니다.
1. Object.keys()로 객체의 모든 키를 순회합니다.
2. 각 키를 split('_')으로 나눠 사람 이름과 속성명(age, height, weight)을 분리합니다.
3. 속성명은 일관성을 위해 toLowerCase()로 소문자로 통일합니다.
4. 해당 사람의 객체가 아직 없다면 새로 만들고 결과 배열에 추가한 뒤, 속성값을 저장합니다.
이 과정을 코드로 구현하면 다음과 같습니다.
const obj = {
"Person1_Age": 22,
"Person1_Height": 170,
"Person1_Weight": 72,
"Person2_Age": 27,
"Person2_Height": 160,
"Person2_Weight": 56
};
const separateOut = (obj = {}) => {
const res = [];
const map = {}; // 사람 이름을 키로 하는 임시 맵
Object.keys(obj).forEach(el => {
const part = el.split('_');
const person = part[0]; // 예: "Person1"
const info = part[1].toLowerCase(); // 예: "age"
if (!map[person]) {
map[person] = { name: person };
res.push(map[person]);
}
map[person][info] = obj[el];
});
return res;
};
console.log(separateOut(obj));실행 결과
콘솔에는 각 사람별로 묶인 객체 배열이 출력됩니다.
[
{ name: 'Person1', age: 22, height: 170, weight: 72 },
{ name: 'Person2', age: 27, height: 160, weight: 56 }
]코드 설명
map 객체는 이미 생성된 사람 객체를 빠르게 찾기 위한 참조용 맵입니다. 덕분에 같은 사람의 속성이 여러 번 등장해도 중복 객체가 만들어지지 않고, 기존 객체에 값만 추가됩니다. 최종 반환되는 res 배열에는 사람별 객체가 처음 발견된 순서대로 담기게 됩니다.
이 패턴은 로그 데이터 정규화, CSV 파싱 결과 재구성처럼 접두사 기반 키를 그룹 단위 객체로 재조립해야 하는 다양한 상황에 응용할 수 있습니다.