【JavaScript】配列内の同一要素をグループ化してサブ配列にまとめる方法
問題の概要
JavaScriptでは、同じ値が重複して含まれる数値配列から、同一の要素ごとにサブ配列へまとめた新しい配列を作りたい場面があります。本記事では、そのような「同一要素のグループ化」を行う関数の実装方法をわかりやすく解説します。
例えば、入力配列が次のような場合を考えてみましょう。
const arr = [234, 65, 65, 2, 2, 234];
このとき、期待される出力は以下のとおりです。
const output = [[234, 234], [65, 65], [2, 2]];
アプローチ:ハッシュマップで出現位置を管理する
この問題は、ハッシュマップ(プレーンなオブジェクト)を使って「すでに出現した値」と「その値が属するサブ配列のインデックス」を記録することで効率的に解決できます。あとはforループで配列を1回だけ走査し、初めて登場する値なら新しいサブ配列を作成、すでに出現した値なら対応するサブ配列にpush()するだけで実装できます。
コード例
const arr = [234, 65, 65, 2, 2, 234];
const groupArray = arr => {
const map = {};
const group = [];
for (let i = 0; i < arr.length; i++) {
if (typeof map[arr[i]] === 'number') {
// すでに出現済みの値なら、対応するサブ配列に追加
group[map[arr[i]]].push(arr[i]);
} else {
// push()は配列の新しい長さを返すため、
// 新しく追加された要素のインデックスは「長さ - 1」となる
map[arr[i]] = group.push([arr[i]]) - 1;
}
}
return group;
};
console.log(groupArray(arr));実行結果
コンソールには次のように出力されます。
[ [ 234, 234 ], [ 65, 65 ], [ 2, 2 ] ]
コードのポイント
- push()の戻り値を活用:
Array.prototype.push()は要素追加後の配列の長さを返します。新しく作成されたサブ配列のインデックスは「長さ - 1」になるため、これをそのままマップに保存するのがポイントです。 - 優れた計算量: 配列を一度だけ走査するため、時間計算量はO(n)です。空間計算量もO(n)に収まり、大規模な配列でも高速に動作します。
- 出現順の維持: 各グループは値が最初に出現した順番どおりに並ぶため、元の配列の順序情報が保たれます。
補足:Mapを使った別解
ES6で導入されたMapオブジェクトを使えば、より直感的に記述することも可能です。
const groupArray = arr => {
const map = new Map();
for (const num of arr) {
if (!map.has(num)) {
map.set(num, []);
}
map.get(num).push(num);
}
return [...map.values()];
};Mapは挿入順序が保証されているため、こちらの書き方でも値が最初に出現した順番どおりにサブ配列が並びます。可読性を重視する場合はこの方法もおすすめです。
-
JavaScriptのarray.entries()メソッドとは?使い方をサンプルコードで解説
array.entries()メソッドの概要JavaScriptのarray.entries()メソッドは、配列のインデックス(キー)と要素(値)のペアを格納した「Array Iteratorオブジェクト」を返すメソッドです。戻り値であるイテレータはfor...ofループなどで展開でき、配列の各要素とその位置を同時に取得したい場合に便利です。構文array.entries()引数は不要です。呼び出し元の配列に対するイテレータオブジェクトが返されます。サンプルコード1:数値配列での使用例以下の例では、ランキングポイントの配列に対してentries()メソッドを実行し、キーと値のペアを順番に表示し
-
JavaScriptのArray.entries()メソッドとは?使い方とサンプルコードを解説
Array.entries()メソッドとはJavaScript の Array.entries() メソッドは、配列内の各要素を「インデックス(キー)と値」のペアとして格納した、新しい Array Iterator オブジェクトを返します。このオブジェクトは反復可能(iterable)であるため、for...of ループやスプレッド構文などを使って、要素を一つずつ取り出すことができます。基本構文arr.entries()サンプルコード以下は、Array.entries() メソッドを使用して、配列の要素をキー/値ペアとして表示するコード例です。<!DOCTYPE html> <