0

「ポイント」の数に対応する一連のキャンペーンがあります。次のようになります。

[ {"c1":4, "c2":8, "c3":25} ]

このセットからランダムにキャンペーンを選びたいです。rand() はいつか登場すると思います。ただし、それぞれの値が選択される可能性に影響するようにしたいと考えています。

したがって、たとえば、キャンペーン「c2」は、キャンペーン「c1」の 2 倍の頻度で (概算で) 選択する必要があります。「c3」が王様で、選ばれる可能性が最も高いでしょう。

キャンペーンの数と対応する値は、スクリプトを実行するたびに同じになる場合とそうでない場合があります。

これについて行く良い方法は何ですか?

4

2 に答える 2

4

簡単だ。各キャンペーンの CDF 値を持つ別のマップを作成するだけです。あなたの例では、次のようになります。

0.108: C1
0.324: C2
1: C3

次に、0 と 1 の間の乱数を取得します。マップを調べて、乱数よりも大きい最小の数を見つけます (二分検索するか、最小の大きな数を与えることができる並べ替えられたハッシュ マップを作成することもできます)。

確率を追加しても、最後のエントリが 1 にならない場合があることに注意してください (0.999 になる可能性があります)。手動で 1 に設定するだけです。

于 2012-07-18T03:04:22.680 に答える
1

これを解決する関数を次に示します。重み付けされた値ごとに各アイテムを適切に重み付けするために、乱数で使用できる重み付け配列を作成します。

var campaigns = {"c1":4, "c2":8, "c3":24};

function getWeightedRandomCampaign(list) {
    var weighting = [];
    var total = 0;
    for (var item in list) {
        weighting.push({key: item, value: list[item]});
        total += list[item];
    }
    // generate random number between 1 and total
    var rand = Math.floor(Math.random() * total);
    // figure out which weighted slot it fits in
    var cum = 0;
    for (var i = 0; i < weighting.length; i++) {
        cum += weighting[i].value;
        if (rand < cum) {
            return(weighting[i].key);
        }            
    }
    return(weighting[weighting.length - 1]);
}

ここで動作することがわかります: http://jsfiddle.net/jfriend00/ffwqQ/


仕組みは次のとおりです。

キャンペーン オブジェクトと加重値から始めます。

var campaigns = {"c1":4, "c2":8, "c3":24};

次に、次のような一時データ構造を構築します。

var weighting = [{key: "c1", value: 4}, {key: "c2", value: 8}, {key: "c3", value: 24}];

そのデータ構造を作成している間、すべての重量値の現在の合計を追跡します。

次に、0 からその合計までの乱数を作成します。

次に、重み付け配列を調べて値を加算し、乱数を超える最初の累積値を見つけます。それが見つかった場合、これが選択されたスロットです。

于 2012-07-18T03:30:22.690 に答える