19

この質問はさまざまな形で出回っていることは承知していますが、効率に関する私の特定の問題に関する答えを見つけることができませんでした。

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

私はランダムにアイテムを選択する10個のアイテム配列を持っています(Enterキーを押すと)。このコードは、ランダムに選択できない最新の 5 つの選択肢の配列を保持します (時間の経過とともに繰り返されることを避けるため)。

chooseName() 関数が最初に最近の 5 回で使用された名前を選択した場合、関数は単純に壊れて再び自分自身を呼び出し、「一意の」名前が見つかるまで繰り返します。

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);
4

11 に答える 11

36

私はコメンター@YuriyGalanterのアイデアが好きです。すべてが取られるまでアイテムをランダムに選択し、それから繰り返すだけなので、実装は次のとおりです。

function randomNoRepeats(array) {
  var copy = array.slice(0);
  return function() {
    if (copy.length < 1) { copy = array.slice(0); }
    var index = Math.floor(Math.random() * copy.length);
    var item = copy[index];
    copy.splice(index, 1);
    return item;
  };
}

var chooser = randomNoRepeats(['Foo', 'Bar', 'Gah']);
chooser(); // => "Bar"
chooser(); // => "Foo"
chooser(); // => "Gah"
chooser(); // => "Foo" -- only repeats once all items are exhausted.
于 2013-07-26T21:34:41.807 に答える
0

はい、これは再帰的であり、状態を減少させないため、理論的には永遠に続く可能性があります。

配列の変更は許可されていないと思います。そうしないと、最近の選択を配列から削除し、最近の選択がバッファオーバーフローしたときにそれらを押し戻すことができるからです。

代わりに: 配列の末尾にある buffersize 項目を選択から除外します。(Buffersize は 0 から始まり、最近の選択がバッファーに追加されるにつれて、事前設定された buffersizemax まで大きくなります。) 選択を行うときは、buffersize の最近の選択と比較します。一致するものが見つかった場合は、対応する除外アイテムを代わりに選択します。

明らかに、これには、一致を回避するためにバッファ内の最近のすべての選択をチェックする必要があるという非効率性があります。しかし、可能な再帰を回避する効率があります。

于 2016-09-03T21:10:50.887 に答える