JavaScript 개발을 하다 보면 서로 다른 배열에 나뉘어 있는 객체 데이터를 하나의 고유 키(필드)를 기준으로 병합해야 하는 경우가 자주 발생합니다. 이번 글에서는 roll이라는 고유 필드를 기준으로 두 개의 속성을 합친 뒤, 그 결과를 콘솔에 출력하는 방법을 단계별로 알아보겠습니다.
문제 정의
students 객체는 names와 marks라는 두 가지 속성을 가지고 있습니다. names는 각 요소가 name과 roll 속성을 가지는 객체 배열이며, 마찬가지로 marks는 각 요소가 mark와 roll 속성을 가지는 객체 배열입니다. 우리의 목표는 각 객체가 공통으로 가진 roll 값을 기준으로 marks와 names를 하나로 합치는 것입니다.
여기서 사용할 students 객체는 다음과 같습니다.
const students = {
marks: [{
roll: 123,
mark: 89
}, {
roll: 143,
mark: 69
}, {
roll: 126,
mark: 91
}, {
roll: 112,
mark: 80
}],
names: [{
name: 'Aashish',
roll: 126
}, {
name: 'Sourav',
roll: 112
}, {
name: 'Vineet',
roll: 143
}, {
name: 'Kartik',
roll: 123
}]
}속성 병합 함수 구현
이제 combineProperties라는 함수를 정의해 보겠습니다. 이 함수는 students 객체를 인자로 받아, 추가적인 메모리 공간을 사용하지 않고(in-place 방식) 속성들을 병합합니다.
const combineProperties = (students) => {
const { marks, names } = students;
marks.forEach(marksObj => {
const { roll } = marksObj;
marksObj.name = names.find(namesObj => namesObj.roll === roll).name;
})
delete students['names'];
};
combineProperties(students);
console.log(students);코드의 동작 원리를 살펴보면 다음과 같습니다.
forEach()로marks배열을 순회하면서 각 객체의roll값을 추출합니다.Array.prototype.find()메서드를 사용해names배열에서 동일한roll값을 가진 객체를 찾고, 해당 객체의name을marks객체에 추가합니다.- 모든 병합이 완료되면
delete연산자로 더 이상 필요 없는names속성을 제거합니다.
시간 및 공간 복잡도
이 코드의 시간 복잡도는 O(mn)입니다. 여기서 m과 n은 각각 names와 marks 배열의 크기입니다. 공간 복잡도는 O(1)로, 추가 공간 없이 기존 객체를 직접 수정한다는 장점이 있습니다. 다만 marks 배열의 각 요소에 새로운 name 속성이 생성된다는 점은 유의해야 합니다.
팁: 처리해야 할 데이터 양이 많다면 find() 대신 Map 객체를 활용하는 것이 좋습니다. 이렇게 하면 시간 복잡도를 O(m + n)까지 줄일 수 있어 성능이 크게 향상됩니다.
전체 코드
const students = {
marks: [{
roll: 123,
mark: 89
}, {
roll: 143,
mark: 69
}, {
roll: 126,
mark: 91
}, {
roll: 112,
mark: 80
}],
names: [{
name: 'Aashish',
roll: 126
}, {
name: 'Sourav',
roll: 112
}, {
name: 'Vineet',
roll: 143
}, {
name: 'Kartik',
roll: 123
}]
}
const combineProperties = (students) => {
const { marks, names } = students;
marks.forEach(marksObj => {
const { roll } = marksObj;
marksObj.name = names.find(namesObj => namesObj.roll === roll).name;
})
delete students['names'];
};
combineProperties(students);
console.log(students);실행 결과
콘솔 출력 결과는 다음과 같습니다.
{
marks: [
{ roll: 123, mark: 89, name: 'Kartik' },{ roll: 143, mark: 69, name: 'Vineet' },
{ roll: 126, mark: 91, name: 'Aashish' },{ roll: 112, mark: 80, name: 'Sourav' }
]
}출력 결과를 보면 각 marks 객체에 roll 값에 맞는 name이 성공적으로 추가되었고, 불필요해진 names 속성은 깔끔하게 제거된 것을 확인할 수 있습니다. 이처럼 forEach()와 find()를 조합하면 고유 필드를 기준으로 객체 속성을 손쉽게 병합할 수 있습니다.