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

JavaScriptの配列を特定のキー(tableName)ごとにグループ化する方法

JavaScriptでデータを扱っていると、フラットな配列を特定のキーごとにまとめ直したい場面がよくあります。本記事では、tableName プロパティの値を基準に、オブジェクトの配列をグループ化する方法を解説します。

前提となる入力データ

まず、次のような配列があったとします。

const data = [
  {
    "dataId": "1",
    "tableName": "table1",
    "column": "firstHeader",
    "rows": ["a", "b", "c"]
  },
  {
    "dataId": "2",
    "tableName": "table1",
    "column": "secondHeader",
    "rows": ["d", "e", "f"]
  },
  {
    "dataId": "3",
    "tableName": "table2",
    "column": "aNewFirstHeader",
    "rows": [1, 2, 3]
  }
];

ここで求められているのは、元の配列をもとにして、tableName ごとにデータを集約した新しい配列を作成するJavaScriptの関数です。同じテーブル名を持つ要素は1つのオブジェクトに統合し、columnrows はそれぞれ配列として格納します。

最終的に期待される出力は次のとおりです。

const output = [
  {
    "tableName": "table1",
    "column": ["firstHeader", "secondHeader"],
    "rows": [["a", "b", "c"], ["d", "e", "f"]]
  },
  {
    "tableName": "table2",
    "column": ["aNewFirstHeader"],
    "rows": [[1, 2, 3]]
  }
];

実装例:reduce と Map を組み合わせる

それでは、実際のコードを見てみましょう。Array.prototype.reduce()Map を組み合わせることで、シンプルかつ効率的にグループ化できます。

const arr = [
  {
    "dataId": "1",
    "tableName": "table1",
    "column": "firstHeader",
    "rows": ["val", "b", "c"]
  },
  {
    "dataId": "2",
    "tableName": "table1",
    "column": "secondHeader",
    "rows": ["d", "e", "f"]
  },
  {
    "dataId": "3",
    "tableName": "table2",
    "column": "aNewFirstHeader",
    "rows": [1, 2, 3]
  }
];

const groupArray = (arr = []) => {
  const res = arr.reduce((obj => (acc, val) => {
    let item = obj.get(val.tableName);
    if (!item) {
      item = {
        tableName: val.tableName,
        column: [],
        rows: []
      };
      obj.set(val.tableName, item);
      acc.push(item);
    }
    item.column.push(val.column);
    item.rows.push(val.rows);
    return acc;
  })(new Map()), []);
  return res;
};

console.log(JSON.stringify(groupArray(arr), undefined, 4));

コードのポイント

  • Mapによる重複管理: Map を使って tableName をキーとした対応表を作成することで、すでに処理済みのテーブル名かどうかを高速に判定できます。
  • 初回登場時のみオブジェクトを生成: 該当する tableName がまだ存在しない場合のみ、columnrows を持つ空の配列を備えた新規オブジェクトを作成し、Mapと結果配列の両方に登録します。
  • クロージャーの活用: (obj => (acc, val) => {...})(new Map()) の形でMapをクロージャー内に閉じ込めることで、reduceの外部に余計な変数を露出させずに済みます。
  • 値の蓄積: 各要素を処理するたびに、対応するオブジェクトの columnrows へ値を追加していくため、元の配列の順序も保持されます。

出力結果

上記のコードを実行すると、コンソールには次のように出力されます。

[
  {
    "tableName": "table1",
    "column": [
      "firstHeader",
      "secondHeader"
    ],
    "rows": [
      ["val", "b", "c"],
      ["d", "e", "f"]
    ]
  },
  {
    "tableName": "table2",
    "column": [
      "aNewFirstHeader"
    ],
    "rows": [
      [1, 2, 3]
    ]
  }
]

このように、reduceMap を組み合わせれば、元の配列の構造や順序を保ちながら、任意のキーでデータをきれいにグループ化できます。APIレスポンスの整形やテーブル表示用データの変換など、さまざまな場面で応用できるテクニックなので、ぜひ活用してみてください。

  1. JavaScriptにおける配列の分割代入(Destructuring)の基本と使い方

    分割代入(Destructuring)とは、配列から値を取り出して個別の変数に展開するための構文です。ES2015(ES6)で導入されたこの機能を使うと、配列の各要素を簡潔かつ読みやすく変数に割り当てることができます。 配列の分割代入のサンプルコード 以下は、JavaScriptで配列の分割代入を行うコード例です。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport&quo

  2. JavaScriptでIDごとにオブジェクトの配列をグループ化する方法

    JavaScriptでオブジェクトの配列をidなどの特定のキーごとにグループ化したい場合、reduce()メソッドを使うと簡潔に実装できます。この記事では、どのプロパティにも対応できる汎用的なgroupBy関数を作成し、実際のサンプルコードとともにその仕組みを詳しく解説します。 reduce()によるグループ化の考え方 reduce()は、配列の各要素を順番に処理しながら、1つの累積値(ここではオブジェクト)を組み立てていくメソッドです。各要素からキーの値を取り出し、その値がまだ結果オブジェクトに存在しなければ新しい配列を作成して、そこへ要素を追加していくことでグループ化を実現します。 サ