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

JavaScriptでネストされた配列をtypeごとにグループ化する方法


問題の概要

まず、次のようなネストされた構造を持つ配列を考えてみましょう。各要素は、数値の配列 value1 と、type プロパティを持つオブジェクトの配列 value2 から構成されています。

const arr = [
  {
    value1: [1, 2],
    value2: [{ type: 'A' }, { type: 'B' }]
  },
  {
    value1: [3, 5],
    value2: [{ type: 'B' }, { type: 'B' }]
  }
];

求められているのは、このような配列を受け取り、各オブジェクトの type プロパティを基準にデータをグループ化した配列を生成する JavaScript の関数です。

ここでのポイントは、同じ要素の中で同じ type が複数回登場しても、その要素の value1 が重複して連結されないようにする点です。上記の例では2番目の要素に 'B' が2つ含まれていますが、[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 = [];
  // 登録済みの type を管理するオブジェクト
  const registeredTypes = {};
  // 「要素のインデックス|type」単位の処理済みフラグ
  const processedPairs = {};

  arr.forEach((el, ind) => {
    el.value2.forEach(({ type }) => {
      // まだ存在しない type なら、新しいグループを作成
      if (!registeredTypes[type]) {
        registeredTypes[type] = { type, value: [] };
        res.push(registeredTypes[type]);
      }
      // 同じ要素・同じ type の組み合わせは一度だけ処理
      const key = ind + '|' + type;
      if (!processedPairs[key]) {
        registeredTypes[type].value =
          registeredTypes[type].value.concat(el.value1);
        processedPairs[key] = true;
      }
    });
  });

  return res;
};

console.log(groupValues(arr));

出力結果

コンソールには次のように表示されます。

[
  { type: 'A', value: [ 1, 2 ] },
  { type: 'B', value: [ 1, 2, 3, 5 ] }
]

type 'A' は最初の要素にのみ存在するため [1, 2] だけが集まり、type 'B' は両方の要素に存在するため [1, 2][3, 5] が連結された形になっています。

コードの解説

  • 外側の forEach で入力配列の各要素を順に処理し、内側の forEachvalue2 内の各オブジェクトから type を取り出します。
  • registeredTypes に未登録の type である場合は、{ type, value: [] } という形式のグループオブジェクトを新しく作成し、結果配列 res に登録します。
  • 値の連結は「要素のインデックス + '|' + type」というキー(processedPairs)で管理されており、同一要素内に同じ type が何度現れても、value1 の連結は一度しか実行されません。
  • すべての要素を走査し終えたら res を返すことで、type ごとにグループ化された配列が完成します。

まとめ

このように、「登録済みの type」と「処理済みの要素 × type の組み合わせ」を補助オブジェクトで管理するだけで、ネストされた配列をシンプルかつ確実にグループ化できます。APIレスポンスの整形やログデータの集計など、実務でも頻繁に使われるパターンなので、ぜひ活用してみてください。

  1. JavaScriptのslice()メソッドとは?配列から要素を取り出す使い方を実例で解説

    JavaScriptのslice()メソッドは、大きな配列の中から選択した範囲の要素を抜き出し、新しい配列として返すメソッドです。最大の特徴は、元の配列を一切変更しない(非破壊的な操作)という点にあります。そのため、元データを保持したまま部分的なコピーを作りたい場合に非常に便利です。 slice()メソッドの基本構文 arr.slice(start, end) start:取り出しを開始するインデックス番号(省略可・デフォルトは0) end:取り出しを終了する位置の直前のインデックス番号(省略可・デフォルトは配列の末尾まで)。endで指定した要素自体は結果に含まれない点に注意してください。

  2. JavaScriptで2つのオブジェクトを比較しながら配列のネストされた値をグループ化する方法

    この記事では、2つのオブジェクト(before と after)を比較しながら、ネストされた配列の値を1つの行にグループ化する方法を解説します。データの差分を表形式で整理したい場合などに役立つテクニックです。入力データの例まず、次のようなJSONオブジェクトがあるとします。before(変更前)と after(変更後)の2つの状態が含まれ、それぞれの device 配列の中に、id、price、features(機能名と価格)というネストされた構造を持っています。const input = { before: { device: [ { id: 1234