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で入力配列の各要素を順に処理し、内側のforEachでvalue2内の各オブジェクトからtypeを取り出します。 registeredTypesに未登録のtypeである場合は、{ type, value: [] }という形式のグループオブジェクトを新しく作成し、結果配列resに登録します。- 値の連結は「要素のインデックス + '|' + type」というキー(
processedPairs)で管理されており、同一要素内に同じtypeが何度現れても、value1の連結は一度しか実行されません。 - すべての要素を走査し終えたら
resを返すことで、typeごとにグループ化された配列が完成します。
まとめ
このように、「登録済みの type」と「処理済みの要素 × type の組み合わせ」を補助オブジェクトで管理するだけで、ネストされた配列をシンプルかつ確実にグループ化できます。APIレスポンスの整形やログデータの集計など、実務でも頻繁に使われるパターンなので、ぜひ活用してみてください。
-
JavaScriptのslice()メソッドとは?配列から要素を取り出す使い方を実例で解説
JavaScriptのslice()メソッドは、大きな配列の中から選択した範囲の要素を抜き出し、新しい配列として返すメソッドです。最大の特徴は、元の配列を一切変更しない(非破壊的な操作)という点にあります。そのため、元データを保持したまま部分的なコピーを作りたい場合に非常に便利です。 slice()メソッドの基本構文 arr.slice(start, end) start:取り出しを開始するインデックス番号(省略可・デフォルトは0) end:取り出しを終了する位置の直前のインデックス番号(省略可・デフォルトは配列の末尾まで)。endで指定した要素自体は結果に含まれない点に注意してください。
-
JavaScriptで2つのオブジェクトを比較しながら配列のネストされた値をグループ化する方法
この記事では、2つのオブジェクト(before と after)を比較しながら、ネストされた配列の値を1つの行にグループ化する方法を解説します。データの差分を表形式で整理したい場合などに役立つテクニックです。入力データの例まず、次のようなJSONオブジェクトがあるとします。before(変更前)と after(変更後)の2つの状態が含まれ、それぞれの device 配列の中に、id、price、features(機能名と価格)というネストされた構造を持っています。const input = { before: { device: [ { id: 1234