JavaScriptで配列要素の出現回数をカウントし、2次元配列として取得する方法
リテラル値(数値や文字列など)からなる配列を受け取り、それぞれの要素が出現する回数を数えて、その結果をもとに新しい2次元配列を作成するJavaScript関数が必要になる場面は少なくありません。
例えば、次のような入力配列が与えられたとします。
const arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
この場合、期待される出力は以下のとおりです。各サブ配列は「要素の値」と「その出現回数」のペアを表しています。
const output = [
[5, 3],
[2, 5],
[9, 1],
[4, 1]
];
コード例
この処理を実現するコードは以下のようになります。
const arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
const frequencyArray = (arr = []) => {
const map = {}; // 各要素の処理状況を記録するオブジェクト
const res = []; // 結果となる2次元配列
arr.forEach(el => {
if (!map[el]) {
// 初めて登場した要素なら [値, 0] のペアを作成して登録
map[el] = [el, 0];
res.push(map[el]);
}
// 出現回数をインクリメント
map[el][1]++;
});
return res;
};
console.log(frequencyArray(arr));
実行結果
コンソールには次のように出力されます。
[ [ 5, 3 ], [ 2, 5 ], [ 9, 1 ], [ 4, 1 ] ]
コードの解説
この関数の仕組みは非常にシンプルです。
- map オブジェクト:すでに処理済みの要素かどうかを判定するために使います。キーが存在しない場合、その要素は初登場であることが分かります。
- res 配列:[値, 出現回数] 形式のペアを格納する最終的な結果配列です。map[el] には同じ配列への参照が格納されているため、後から map[el][1]++ を実行すると、res 内の対応するペアも自動的に更新されます。
- 計算量:配列の各要素を一度だけ走査するため、計算量は O(n) と効率的です。
別のアプローチ:reduce を使う方法
より関数型的な書き方を好む場合は、Array.prototype.reduce() を使って次のように記述することもできます。
const frequencyArray = (arr = []) =>
Object.entries(
arr.reduce((acc, el) => {
acc[el] = (acc[el] || 0) + 1;
return acc;
}, {})
).map(([key, count]) => [Number(key), count]);
console.log(frequencyArray([5, 5, 5, 2, 2, 2, 2, 2, 9, 4]));
// [ [ 5, 3 ], [ 2, 5 ], [ 9, 1 ], [ 4, 1 ] ]
この方法では、まず reduce で { 要素: 出現回数 } 形式のオブジェクトを作成し、その後 Object.entries() で [キー, 値] の配列へ変換しています。オブジェクトのキーは文字列として扱われるため、Number() を適用して元の数値型に戻している点に注意してください。
どちらの方法でも目的の結果は得られますが、単純なループ処理で十分な場合は最初の forEach 版、集計ロジックを一段落として記述したい場合は reduce 版がおすすめです。
-
JavaScriptの_.initial()関数とは?配列の末尾要素を除外する方法を解説
_.initial()関数とは_.initial()は、JavaScriptのライブラリであるUnderscore.jsに含まれる関数の一つです。このメソッドは、配列の最後の要素とそれ以外の要素を区別し、末尾の要素を除外した結果を取得したい場合に活用されます。つまり、配列の最後の値だけを無視して、残りのすべての要素を取り出すことができる便利な関数です。基本構文_.initial( array, n );_.initial()は、最大2つのパラメータを受け取ることができます。array(必須):対象となる配列です。このメソッドは、渡された配列から最後の要素を除いた、残りすべての要素を返します。n
-
JavaScriptで配列の要素を同じ配列内に複製する方法
JavaScriptでは、concat()メソッドとsort()メソッドを組み合わせることで、既存の配列の要素を同じ配列内に複製することができます。ここでは、実際に動作するサンプルコードを使って、その手順をわかりやすく解説します。 コード例 以下は、配列の要素を同じ配列内に複製するためのコード例です。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" cont