JavaScriptで配列を同じ値ごとにグループ化してカウントする方法
はじめに
文字列や数値のリテラルを含む配列の中に、重複した値がいくつか存在するケースを考えてみましょう。
const array = ['day', 'night', 'afternoon', 'night', 'noon', 'night', 'noon', 'day', 'afternoon', 'day', 'night'];
ここで必要なのは、このような配列を受け取り、重複している要素をサブ配列の最初の要素としてグループ化し、元の配列における出現回数を2番目の要素として格納した新しい配列を返す関数 groupSimilar() を作成することです。
上記の例の場合、期待される出力は以下のようになります。
[ [ 'day', 3 ], [ 'night', 4 ], [ 'afternoon', 2 ], [ 'noon', 2 ] ]
コード例
それでは、実際にこの関数を実装してみましょう。配列の反復処理には Array.prototype.reduce() を使用し、各値がどのインデックス位置にあるかを追跡するために Map オブジェクトを活用します。
const array = ['day', 'night', 'afternoon', 'night', 'noon', 'night',
'noon', 'day', 'afternoon', 'day', 'night'];
const groupSimilar = arr => {
return arr.reduce((acc, val) => {
const { data, map } = acc;
const ind = map.get(val);
if(map.has(val)){
data[ind][1]++;
} else {
map.set(val, data.push([val, 1])-1);
}
return { data, map };
}, {
data: [],
map: new Map()
}).data;
};
console.log(groupSimilar(array));処理の流れ
- アキュムレータ(
acc)には、結果を格納するdata配列と、値とインデックスの対応を管理するmapの2つを持たせています。 - 各要素(
val)を走査し、すでにmapに登録済みであれば、対応するdataのカウントを1つ増やします。 - 未登録の値であれば、
[val, 1]を新規に追加し、そのインデックスをmapに記録します。
この仕組みにより、配列を一度だけ走査するだけでグループ化とカウントを同時に完了できるため、パフォーマンス面でも効率的です。
実行結果
コンソールには以下のように出力されます。
[ [ 'day', 3 ], [ 'night', 4 ], [ 'afternoon', 2 ], [ 'noon', 2 ] ]
-
JavaScriptのArray.values()メソッドとは?使い方とサンプルコードを徹底解説
JavaScriptのArray.values()メソッドとは? JavaScriptのArray.values()メソッドは、対象の配列に含まれるすべての値を格納したイテレーターオブジェクトを返します。ES2015(ES6)以降で利用可能なこのメソッドは、for...ofループやスプレッド構文([...arr])と組み合わせることで、配列の各要素を効率的に取り出せます。 なお、keys()やentries()がインデックス情報も一緒に返すのに対し、values()は純粋に「値」だけを順番に提供する点が大きな特徴です。 基本構文 arr.values() 引数は不要で、戻り値として新しいArr
-
JavaScriptでIDごとにオブジェクトの配列をグループ化する方法
JavaScriptでオブジェクトの配列をidなどの特定のキーごとにグループ化したい場合、reduce()メソッドを使うと簡潔に実装できます。この記事では、どのプロパティにも対応できる汎用的なgroupBy関数を作成し、実際のサンプルコードとともにその仕組みを詳しく解説します。 reduce()によるグループ化の考え方 reduce()は、配列の各要素を順番に処理しながら、1つの累積値(ここではオブジェクト)を組み立てていくメソッドです。各要素からキーの値を取り出し、その値がまだ結果オブジェクトに存在しなければ新しい配列を作成して、そこへ要素を追加していくことでグループ化を実現します。 サ