2017-07-05 8 views
1

配列からランダムな項目を選択したいのですが、確かに確率分布があります。 は、現在、私は:私は95確率分布でランダムサンプリングを行うより良い方法は?

を得るための5〜25%の確率を得るための、75%の確率で取得 myarray =[5,5,5,95] を私はしかし、より多くの数字を持っており、それがすべてのそれらを書き出すために時間がかかりすぎます数字は、これを行うより速く/より良い方法がありますか?

答えて

2

valuechanceプロパティの値が01のオブジェクトを持つ配列を持つことができます。アレイ内のすべてのchanceプロパティの合計が1に合計する必要があり、その後、あなたはこのような機能を持つことができます。

// data 
 
var samples = [ 
 
    { 
 
    value: 5, 
 
    chance: .75 
 
    }, { 
 
    value: 95, 
 
    chance: .25 
 
    } 
 
]; 
 

 
// requested method 
 
function randomSample(samples) { 
 
    var sample = Math.random(); 
 
    
 
    return samples.find(
 
    element => (sample -= element.chance) < 0 
 
).value; 
 
} 
 

 
// demo 
 
var counts = Array(100).fill() 
 
    .map(() => randomSample(samples)) 
 
    .reduce((acc, val) => (acc[val]++, acc), { 5: 0, 95: 0}); 
 

 
console.log(counts);

この方法の利点は、オブジェクトが持っていないということです任意の特定の順序で配列に格納されます。

2

function weightedChoice(array, weights) { 
 
    let s = weights.reduce((a, e) => a + e); 
 
    let r = Math.random() * s; 
 
    return array.find((e, i) => (r -= weights[i]) < 0); 
 
} 
 

 
let randomArray = 
 
    Array.apply(null, Array(32)). 
 
    map(() => weightedChoice([5, 95], [75, 25])); 
 
console.log(JSON.stringify(randomArray));

EDIT:パトリックは少し速く私よりだったので、私は彼の答えを支持するだろう、と私はちょうどあなたが絶対に1ように合計を必要としないことを追加します、あなたは自分で合計を見つけることによって体重を正常化することができます。

+0

これも良いです。これは、ウェイトを1にする必要はないという利点があると思います。ただし、ランダムな選択肢を計算する前に、合計を決める余分なループを含める必要があるという欠点があります。 –

+0

@PatrickRoberts:私はちょうどそれを書いていました...:D – Amadan

+0

このアルゴリズムは[This Python implementation](https://stackoverflow.com/a/3679747/5743988)のJSバージョンに似ています。 – 4castle

関連する問題