1. ホーム
  2. javascript

[解決済み] 繰り返しのない配列を効率的に選択する方法は?

2022-02-07 22:57:15

質問

この質問は様々な形で出回っていることは承知していますが、私の具体的な効率化の問題に関連する答えを見つけることができません。

私は以下のコードを持っていますが、うまく動作しています。

10項目の配列があり、そこからランダムに1項目を選択します(エンターキー押下時)。このコードでは、ランダムに選択できない直近の5つの選択肢を配列として保持しています(時間が経つと繰り返しが多くなるのを避けるため)。

chooseName()関数が最初に最近5回使用された名前を選択した場合、単に中断して再度自分自身を呼び出し、quot;ユニーク"な名前を見つけるまで繰り返すだけです。

2つ質問があります。

  1. これは "再帰関数" と言っていいのでしょうか?

  2. 理論的には、一意な名前を見つけるまでに長い時間ループし続ける可能性があることが心配です - これを行うより効率的な方法はありますか?

よろしくお願いします。

    var a = ["Roger", "Russell", "Clyde", "Egbert", "Clare", "Bobbie", "Simon", "Elizabeth", "Ted", "Caroline"];
    var b = [];

    var chooseName = function () {
    var unique = true;
    b.length = 5;
    num = Math.floor(Math.random() * a.length);
    name = a[num];    
        for (i = 0; i < a.length; i++) {
        if (b[i] == name) {
            chooseName();
            unique = false;
            break;
            }
        }
        if (unique == true) {
        alert(name);
        b.unshift(name);
        }
    }


    window.addEventListener("keypress", function (e) {
        var keycode = e.keyCode;
        if (keycode == 13) {
        chooseName();
        }
    }, false);

解決方法は?

アイテムが選択されるたびに、そのアイテムを配列の後ろに移動させ、元の配列のスライスからランダムに選択します。 array.slice(0, -5) .

var a = ["Roger", "Russell", "Clyde", "Egbert", "Clare", "Bobbie", "Simon", "Elizabeth", "Ted", "Caroline"];

var chooseName = function () {
    var unique = true;
    num = Math.floor(Math.random() * a.length - 5);
    name = a.splice(num,1);
    a.push(name);
}


window.addEventListener("keypress", function (e) {
    var keycode = e.keyCode;
    if (keycode == 13) {
        chooseName();
    }
}, false);

EDIT: これはまた、リストの末尾にある変数が最初のN回の呼び出しで考慮されないという不公平な不利益を与えないという副次的効果もあります。もしこれが問題なら、使用するスライスのサイズを記録するスタティック変数をどこかに保持して、B(この場合は5)で最大にするようにするといいかもしれません。 例

var a = ["Roger", "Russell", "Clyde", "Egbert", "Clare", "Bobbie", "Simon", "Elizabeth", "Ted", "Caroline"];
B = 5; //max size of 'cache'
N = 0;

var chooseName = function () {
    var unique = true;
    num = Math.floor(Math.random() * a.length - N);
    N = Math.min(N + 1, B);
    name = a.splice(num,1);
    a.push(name);
}