Weighted random selection from array

后端 未结 13 1871
醉酒成梦
醉酒成梦 2020-11-28 03:13

I would like to randomly select one element from an array, but each element has a known probability of selection.

All chances together (within the array) sums to 1.<

13条回答
  •  一整个雨季
    2020-11-28 03:35

    the trick could be to sample an auxiliary array with elements repetitions which reflect the probability

    Given the elements associated with their probability, as percentage:

    h = {1 => 0.5, 2 => 0.3, 3 => 0.05, 4 => 0.05 }
    
    auxiliary_array = h.inject([]){|memo,(k,v)| memo += Array.new((100*v).to_i,k) }   
    
    ruby-1.9.3-p194 > auxiliary_array 
     => [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,                                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4] 
    
    auxiliary_array.sample
    

    if you want to be as generic as possible, you need to calculate the multiplier based on the max number of fractional digits, and use it in the place of 100:

    m = 10**h.values.collect{|e| e.to_s.split(".").last.size }.max
    

提交回复
热议问题