JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

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 版がおすすめです。

  1. JavaScriptの_.initial()関数とは?配列の末尾要素を除外する方法を解説

    _.initial()関数とは_.initial()は、JavaScriptのライブラリであるUnderscore.jsに含まれる関数の一つです。このメソッドは、配列の最後の要素とそれ以外の要素を区別し、末尾の要素を除外した結果を取得したい場合に活用されます。つまり、配列の最後の値だけを無視して、残りのすべての要素を取り出すことができる便利な関数です。基本構文_.initial( array, n );_.initial()は、最大2つのパラメータを受け取ることができます。array(必須):対象となる配列です。このメソッドは、渡された配列から最後の要素を除いた、残りすべての要素を返します。n

  2. JavaScriptで配列の要素を同じ配列内に複製する方法

    JavaScriptでは、concat()メソッドとsort()メソッドを組み合わせることで、既存の配列の要素を同じ配列内に複製することができます。ここでは、実際に動作するサンプルコードを使って、その手順をわかりやすく解説します。 コード例 以下は、配列の要素を同じ配列内に複製するためのコード例です。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" cont