Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript: 고유 필드(roll)를 기준으로 객체 속성 병합 후 결과 출력하기

JavaScript 개발을 하다 보면 서로 다른 배열에 나뉘어 있는 객체 데이터를 하나의 고유 키(필드)를 기준으로 병합해야 하는 경우가 자주 발생합니다. 이번 글에서는 roll이라는 고유 필드를 기준으로 두 개의 속성을 합친 뒤, 그 결과를 콘솔에 출력하는 방법을 단계별로 알아보겠습니다.

문제 정의

students 객체는 namesmarks라는 두 가지 속성을 가지고 있습니다. names는 각 요소가 nameroll 속성을 가지는 객체 배열이며, 마찬가지로 marks는 각 요소가 markroll 속성을 가지는 객체 배열입니다. 우리의 목표는 각 객체가 공통으로 가진 roll 값을 기준으로 marksnames를 하나로 합치는 것입니다.

여기서 사용할 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 값을 가진 객체를 찾고, 해당 객체의 namemarks 객체에 추가합니다.
  • 모든 병합이 완료되면 delete 연산자로 더 이상 필요 없는 names 속성을 제거합니다.

시간 및 공간 복잡도

이 코드의 시간 복잡도는 O(mn)입니다. 여기서 m과 n은 각각 namesmarks 배열의 크기입니다. 공간 복잡도는 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()를 조합하면 고유 필드를 기준으로 객체 속성을 손쉽게 병합할 수 있습니다.