JavaScriptで配列内の要素が指定回数を超える出現を削除する方法
問題
最初の引数として数値の配列、2番目の引数として整数を受け取るJavaScript関数を作成する必要があります。
この関数は、配列から余分な出現を削除し、処理後の配列内のどの要素も指定された回数(第2引数)より多く出現しないようにします。つまり、各要素の出現回数を上限値までに制限するのが目的です。
アプローチ
この問題は、各要素の出現回数を記録するマップ(オブジェクト)を使うことで効率的に解決できます。手順は以下の通りです。
- 配列を走査し、各要素の出現回数をカウントします。ただし、カウントが指定された上限値に達したらそれ以上は増やしません。
- カウント結果をもとに、各要素を許容回数だけ新しい配列に追加します。
- 最後に、文字列化された値を数値に戻して返します。
コード例
以下がそのコードです −
const arr = [4, 2, 3, 2, 4, 2, 2, 4];
const num = 2;
const deleteExcess = (arr = [], num = 1) => {
const map = {};
for(let i = 0; i < arr.length; i++){
if(!map[arr[i]]){
map[arr[i]] = 1;
}else if(map[arr[i]] + 1 <= num){
map[arr[i]]++;
}
}
const res = [];
Object.keys(map).forEach(key => {
for(let j = 0; j < map[key]; j++){
res.push(key);
}
});
return res.map(Number);
};
console.log(deleteExcess(arr, num));
コードの解説
- カウントフェーズ: 1つ目のループでは、
mapオブジェクトを使って各要素の出現回数を記録します。if(!map[arr[i]])で初登場かどうかを判定し、すでに存在する場合は上限numを超えない範囲でのみカウントを増やします。 - 再構築フェーズ:
Object.keys(map)で各要素のキーを取り出し、記録された回数だけ結果配列resに値を追加します。 - 型変換: オブジェクトのキーは文字列になるため、
res.map(Number)で数値に変換して返しています。
出力
コンソールには次のように表示されます −
[ 2, 2, 3, 4, 4 ]
元の配列では「2」が4回、「4」が3回出現していましたが、出力結果ではどの要素も2回(num の値)を超えていないことが確認できます。
補足:順序と別の実装方法
なお、上記の実装では Object.keys() の仕様により、整数のようなキーは自動的に昇順へ並べ替えられるため、結果の配列は元の順序ではなくソートされた順序になります。
元の配列の順序を保ちたい場合は、filter() を使った次のような実装がシンプルでおすすめです。
const deleteExcess = (arr = [], num = 1) => {
const counts = {};
return arr.filter(item => {
counts[item] = (counts[item] || 0) + 1;
return counts[item] <= num;
});
};
console.log(deleteExcess([4, 2, 3, 2, 4, 2, 2, 4], 2));
// 出力: [ 4, 2, 3, 2, 4 ]
こちらは配列を1回の走査で処理でき、元の順序が維持される点でも実用的です。いずれの方法も計算量はO(n)で、配列を一度だけ走査すればよいため、大きなデータセットにも対応できます。
-
JavaScriptで親要素にアクセスする方法【parentNodeプロパティの使い方】
JavaScriptでDOM操作を行っていると、ある要素の親要素にアクセスしたい場面によく出会います。そんなときに活躍するのがparentNodeプロパティです。このプロパティは、対象ノードの直接の親ノードを返します。 本記事では、クリックイベントとparentNodeプロパティを組み合わせて、クリックされた子要素の親要素を取得し、そのクラス名を画面に表示するサンプルコードを紹介します。 コード例 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8&qu
-
JavaScriptのimportで波括弧「{}」を使う理由とは?名前付きエクスポートの基本をわかりやすく解説
JavaScript(ESモジュール)でモジュールを読み込む際、import 文に波括弧 { } を付けるかどうか迷ったことはありませんか?実はこの波括弧は、名前付きエクスポート(named export)を読み込むために必要な記法です。本記事では、実際のコード例を使いながら、{ } の役割と使い方を詳しく解説します。 importで { } を使う場面とは JavaScriptのESモジュールでは、エクスポート方法によって読み込み側の書き方が変わります。 名前付きエクスポート:export { 関数名 } のようにエクスポートされたものを読み込む場合は、import { 名前 } fro