JavaScriptで要素をグループ化し、重複の出現回数をカウントする効率的なアルゴリズム
JavaScriptでは、複数のオブジェクトが格納された配列から、特定のプロパティ値が一致するデータ同士を「重複」とみなし、それらをグループ化して出現回数を集計したいケースがあります。
本記事では、配列内のオブジェクトを指定したキーでグループ化し、「重複」が何回発生したかという情報も合わせて保持する方法を解説します。
やりたいこと
まず、以下のようなデータがあると仮定します。
X A B O
Y X Z I
Y X Z U
X A B L
Y X Z K
このデータを最初の値でグループ化することを目標とします。重複している行では他の2つのプロパティも同じになっていますが、比較は最初の値だけで十分です。
最終的にユーザーへ表示したい結果は、次のような形式になります。
Y X Z (3)
X A B (2)
サンプルコード
実際のコードは以下の通りです。
const arr = [
{x: 'x', acc: 'acc', val: 'val'},
{y: 'y', x: 'x', z: 'z'},
{y: 'y', x: 'x', z: 'z'},
{x: 'x', c: 'c', val: 'val'}
];
const countOccurrence = (arr = []) => {
const res = {};
arr.forEach (item => {
Object.keys( item ).forEach (prop => {
( res[prop] ) ? res[prop] += 1 : res[prop] = 1;
});
});
return res;
}
const groupByOccurrence = (data = []) => {
const obj = countOccurrence(data);
const res = Object.keys ( obj ).reduce ( ( acc, val ) => {
( acc[obj[val]] ) ? acc[obj[val]].push ( val ) : acc[obj[val]] = [val];
return acc;
}, {});
return res;
}
console.log(groupByOccurrence(arr));
コードの解説
- countOccurrence関数: 配列内の各オブジェクトに対してObject.keys()でキー(プロパティ名)を取得し、そのキーが全体で何回出現するかをカウントします。
- groupByOccurrence関数: 上記のカウント結果を受け取り、reduce()メソッドを使って「出現回数 → プロパティ名のリスト」という対応関係を持つ新しいオブジェクトを生成します。
実行結果
コンソールには以下のように出力されます。
{ '1': [ 'acc', 'c' ], '2': [ 'val', 'y', 'z' ], '4': [ 'x' ] }この結果は、キー「x」が4つのオブジェクトすべてに出現している一方、「val」「y」「z」はそれぞれ2回、「acc」「c」は1回のみ出現していることを示しています。
まとめ
このように、forEach()とreduce()を組み合わせることで、シンプルかつ効率的にグループ化と出現回数の集計を実現できます。計算量はデータ件数に比例するO(n)となるため、大量のデータを扱う場合でも高速に動作します。さらに、MapオブジェクトやArray.prototype.reduce()を工夫すれば、任意のキーによる柔軟なグルーピング処理への応用も可能です。
-
ユークリッドの互除法を使ってJavaScriptで最大公約数(GCD)を求める方法
数学におけるユークリッドの互除法(Euclids algorithm)とは、2つの数の最大公約数(GCD)、すなわち両方の数を余りなく割り切れる最大の数を求めるための古典的なアルゴリズムです。このアルゴリズムは、「2つの数の最大公約数は、大きい方の数を『大きい数から小さい数を引いた差』に置き換えても変化しない」という原理に基づいています。例えば、252 と 105 の最大公約数は 21 です(252 = 21 × 12、105 = 21 × 5)。同様に、105 と 147(= 252 − 105)の最大公約数もやはり 21 になります。この置き換えを行うたびにペアの中の大きい方の数は必ず小さ
-
JavaScriptで複数の文字列に共通する文字を重複込みで抽出する方法
問題文字列の配列 arr を第一引数(かつ唯一の引数)として受け取るJavaScript関数を作成することを考えます。この関数の役割は、配列内のすべての文字列に出現する文字を抽出し、それらを配列として返すことです。重複も含めて扱う必要がある点に注意してください。たとえば、ある文字がすべての文字列の中で2回ずつ出現している場合(3回ではない場合)、最終的な結果にもその文字を2回だけ含めます。入力と出力の例たとえば、関数への入力が次のような場合を考えてみましょう。const arr = [door, floor, crook];r は3つの文字列すべてに1回ずつ現れ、o は door に2回、fl