JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

【JavaScript】一意のキー(roll番号)を使ってオブジェクトのプロパティをマージする方法

本記事では、namesmarks という2つのプロパティを持つ students オブジェクトを例に、共通する一意のキーを手がかりにデータを統合する方法を解説します。

問題の概要

students オブジェクトは以下のような構造になっています。names は各要素が nameroll プロパティを持つオブジェクトの配列、marks は各要素が markroll プロパティを持つオブジェクトの配列です。

今回のタスクは、各オブジェクトが共通して持つ roll プロパティ(出席番号)を照合し、marksnames の情報を1つにまとめることです。

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)でプロパティを統合する関数 combineProperties を定義します。処理の流れは以下の通りです。

  • marks 配列を forEach で走査する
  • 各要素の roll をもとに、names 配列から一致するオブジェクトを find() で検索する
  • 見つかった namemarks 側のオブジェクトに新しいプロパティとして追加する
  • 最後に不要になった names プロパティを削除する
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);

このコードの時間計算量は O(mn) です(m と n はそれぞれ names 配列と marks 配列のサイズ)。空間計算量は O(1) ですが、marks 配列の各要素に新しい name プロパティが追加される点には注意が必要です。

完全なサンプルコード

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 番号を持つ生徒の名前が結合されていることが確認できます。

{
   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' }
   ]
}

応用:Map を使って高速化する

上記の実装は find() を使用しているため、データ件数が増えると計算量 O(m × n) がボトルネックになります。大規模なデータを扱う場合は、あらかじめ namesroll をキーとした Map に変換しておくことで、時間計算量を O(m + n) まで改善できます。

const combinePropertiesOptimized = (students) => {
   const { marks, names } = students;
   const nameMap = new Map(names.map(n => [n.roll, n.name]));
   marks.forEach(obj => {
      obj.name = nameMap.get(obj.roll);
   });
   delete students['names'];
};

このように、一意のキーをもとにオブジェクト配列をマージする処理は、API レスポンスの整形やデータ集計など、実務でも頻繁に登場するパターンです。データ規模に応じて find()Map を使い分けるとよいでしょう。

  1. JavaScriptで別のオブジェクトを介してオブジェクトにアクセスする方法

    JavaScriptでは、あるオブジェクトを定義する際に、別のオブジェクトのプロパティやメソッドを参照することで、その値を取得したり、メソッドの実行結果を利用したりすることができます。この記事では、既存のオブジェクト(obj)を介して、新しいオブジェクト(obj2)からプロパティやメソッドにアクセスする方法を、具体的なコード例とともに解説します。押さえておきたいポイントオブジェクトリテラルの中で obj.lastName のように記述すると、その時点での値が新しいオブジェクトにコピーされます。obj.welcome() のようにメソッド名の後に括弧を付けると、オブジェクト定義時にメソッドが即座

  2. 【JavaScript入門】Symbolを使ってオブジェクトごとに一意のIDを作成する方法

    はじめにJavaScriptでオブジェクトごとに一意のIDを作成したい場合、Symbol()を使うのが最も簡単かつ確実な方法です。Symbolは呼び出されるたびに必ず新しい一意の値を生成するため、たとえ同じ説明文字列を渡しても、二度と同じ値にはなりません。以下は、各オブジェクトに対して一意のIDを作成するサンプルコードです。実装例<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewp