문제 소개
다음과 같이 값들이 담긴 배열이 있다고 가정해 보겠습니다.
const arr = [
{
value1:[1,2],
value2:[{type:'A'}, {type:'B'}]
},
{
value1:[3,5],
value2:[{type:'B'}, {type:'B'}]
}
];
배열의 각 요소는 두 개의 속성을 가진 객체입니다. value1은 숫자 배열이며, value2는 type 속성을 가진 객체들의 배열입니다. 우리가 작성해야 할 JavaScript 함수는 이러한 배열을 입력으로 받아, 객체의 "type" 속성을 기준으로 데이터를 그룹화한 새로운 배열을 반환하는 역할을 합니다.
따라서 위 배열에 대한 최종 출력은 다음과 같은 형태가 됩니다.
const output = [
{type:'A', value: [1,2]},
{type:'B', value: [3,5]}
];
예제 코드
이를 구현한 코드는 다음과 같습니다.
const arr = [
{
value1:[1,2],
value2:[{type:'A'}, {type:'B'}]
},
{
value1:[3,5],
value2:[{type:'B'}, {type:'B'}]
}
];
const groupValues = (arr = []) => {
const res = [];
arr.forEach((el, ind) => {
const thisObj = this;
el.value2.forEach(element => {
if (!thisObj[element.type]) {
thisObj[element.type] = {
type: element.type,
value: []
}
res.push(thisObj[element.type]);
};
if (!thisObj[ind + '|' + element.type]) {
thisObj[element.type].value =
thisObj[element.type].value.concat(el.value1);
thisObj[ind + '|' + element.type] = true;
};
});
}, {})
return res;
};
console.log(groupValues(arr));
코드 동작 원리
- 외부 순회:
forEach()를 사용해 입력 배열의 각 객체를 하나씩 순회합니다. - 그룹 추적: 빈 객체(
{})를thisArg로 전달하여, 이미 생성된 type 그룹을 키로 저장함으로써 중복 생성을 방지합니다. - 그룹 생성:
value2의 각 요소를 확인하여 해당 type의 그룹이 아직 없으면 새로 만들고, 결과 배열res에 추가합니다. - 중복 병합 방지:
인덱스|type형태의 키를 활용해, 같은 객체 안에서 동일한 type이 여러 번 등장하더라도value1이 한 번만 병합되도록 처리합니다. - 값 병합:
concat()메서드로value1의 값들을 해당 그룹의value배열에 누적합니다.
출력 결과
콘솔에 출력되는 실행 결과는 다음과 같습니다.
[
{ type: 'A', value: [ 1, 2 ] },
{ type: 'B', value: [ 1, 2, 3, 5 ] }
]
여기서 주목할 점은 첫 번째 객체의 value2에도 type 'B'가 포함되어 있다는 것입니다. 따라서 B 그룹에는 첫 번째 객체의 값([1, 2])과 두 번째 객체의 값([3, 5])이 모두 병합되어 [1, 2, 3, 5]가 됩니다. 반면 type 'A'는 첫 번째 객체에만 존재하므로 [1, 2]만 담게 됩니다.