JavaScriptで配列を並べ替えずに一意な要素の数をカウントする方法
文字列リテラルを含む配列の中に、重複した値がいくつか混在しているケースを考えてみましょう。
const arr = ['Cat', 'Dog', 'Cat', 'Elephant', 'Dog', 'Grapes', 'Dog', 'Lion', 'Grapes', 'Lion'];
ここで求められているのは、配列内に存在する一意(ユニーク)な要素の個数を返す関数です。この処理には Array.prototype.reduce() と Array.prototype.lastIndexOf() を組み合わせて使用します。
仕組みの解説
lastIndexOf() は、指定した値が配列内で最後に出現するインデックスを返すメソッドです。そのため、「現在走査中のインデックス」と「その値の最後の出現位置」が一致するとき、その値は一意な要素として1回だけカウントされることになります。reduce() の初期値を 0 とし、条件を満たすたびに累積値を増やしていくことで、重複を除いた要素の総数が求められます。
実装例
const arr = ['Cat', 'Dog', 'Cat', 'Elephant', 'Dog', 'Grapes', 'Dog',
'Lion', 'Grapes', 'Lion'];
const countUnique = arr => {
return arr.reduce((acc, val, ind, array) => {
if(array.lastIndexOf(val) === ind){
return ++acc;
};
return acc;
}, 0);
};
console.log(countUnique(arr));出力結果
コンソールには次のように表示されます。
5
この配列には 'Cat'、'Dog'、'Elephant'、'Grapes'、'Lion' の5種類の値が存在するため、結果は 5 となります。
このアプローチの利点は、元の配列を一切並べ替えず、新しい配列を生成することもない点です。ソート処理のような副作用がないため、元データの順序を保持したまま、一意な要素の数だけを手軽に取得できます。なお、計算量は各要素ごとに lastIndexOf() が配列全体を走査するため O(n²) となります。大規模な配列を扱う場合は、Set オブジェクトを利用して new Set(arr).size とする方法(O(n))も検討するとよいでしょう。
-
【JavaScript】ネストされた配列の全要素数(ディープカウント)を求める方法
問題:ネストされた配列の全要素数を数える入れ子(ネスト)構造を持つ配列を受け取り、その中に存在するすべての要素の総数(ディープカウント)を返すJavaScript関数を作成します。入力const arr = [1, 2, [3, 4, [5]]];出力const output = 7;出力が7になるのは、第1階層に「1」「2」「[3, 4, [5]]」の3つ、第2階層に「3」「4」「[5]」の3つ、第3階層に「5」の1つの要素が存在し、入れ子の配列そのものも1つの要素としてカウントされるためです。すなわち 3 + 3 + 1 = 7 となります。サンプルコードconst arr = [1, 2
-
JavaScriptで配列を出現頻度の昇順に並べ替える方法
問題数値の配列 arr を唯一の引数として受け取るJavaScript関数を作成する必要があります。配列 arr には重複した要素が含まれている可能性があります。この関数では、出現回数が少ない要素から順に配列を並べ替えます。つまり、出現頻度の低い要素を先頭に配置し、頻度の昇順に沿って残りの要素を並べていきます。なお、出現回数が同じ要素が複数存在する場合は、それらを値の昇順(小さい順)に配置する必要があります。入力例const arr = [5, 4, 5, 4, 2, 1, 12];出力例[1, 2, 12, 4, 4, 5, 5]出力の解説数値「1」「2」「12」はそれぞれ1回しか出現しない