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

JavaScriptで配列内の要素が指定回数を超える出現を削除する方法


問題

最初の引数として数値の配列、2番目の引数として整数を受け取るJavaScript関数を作成する必要があります。

この関数は、配列から余分な出現を削除し、処理後の配列内のどの要素も指定された回数(第2引数)より多く出現しないようにします。つまり、各要素の出現回数を上限値までに制限するのが目的です。

アプローチ

この問題は、各要素の出現回数を記録するマップ(オブジェクト)を使うことで効率的に解決できます。手順は以下の通りです。

  1. 配列を走査し、各要素の出現回数をカウントします。ただし、カウントが指定された上限値に達したらそれ以上は増やしません。
  2. カウント結果をもとに、各要素を許容回数だけ新しい配列に追加します。
  3. 最後に、文字列化された値を数値に戻して返します。

コード例

以下がそのコードです −

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)で、配列を一度だけ走査すればよいため、大きなデータセットにも対応できます。


  1. JavaScriptで親要素にアクセスする方法【parentNodeプロパティの使い方】

    JavaScriptでDOM操作を行っていると、ある要素の親要素にアクセスしたい場面によく出会います。そんなときに活躍するのがparentNodeプロパティです。このプロパティは、対象ノードの直接の親ノードを返します。 本記事では、クリックイベントとparentNodeプロパティを組み合わせて、クリックされた子要素の親要素を取得し、そのクラス名を画面に表示するサンプルコードを紹介します。 コード例 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8&qu

  2. JavaScriptのimportで波括弧「{}」を使う理由とは?名前付きエクスポートの基本をわかりやすく解説

    JavaScript(ESモジュール)でモジュールを読み込む際、import 文に波括弧 { } を付けるかどうか迷ったことはありませんか?実はこの波括弧は、名前付きエクスポート(named export)を読み込むために必要な記法です。本記事では、実際のコード例を使いながら、{ } の役割と使い方を詳しく解説します。 importで { } を使う場面とは JavaScriptのESモジュールでは、エクスポート方法によって読み込み側の書き方が変わります。 名前付きエクスポート:export { 関数名 } のようにエクスポートされたものを読み込む場合は、import { 名前 } fro