繁体   English   中英

在Ruby中,如何通过最小权重进行加权随机选择?

[英]In Ruby, how can one make a weighted random selection by least weight?

如果我有阵列:

ar = [1,3,5,3,6,1,4,6,7,6,6,6,6,6]

我可以将其减少到发生的数量:

counts = {1=>2, 3=>2, 5=>1, 6=>7, 4=>1, 7=>1}

现在我想随意选择与使用最少的数量ar 更加加权

我理解如何根据最常用的数字轻松做出加权随机选择,但不能反过来。

看起来这对你有用:

arr = [1,3,5,3,6,1,4,6,7,6,6,6,6,6]

arr.group_by(&:itself).transform_values{|v| arr.size / v.size}.flat_map do |k,v| 
 [k] * v
end.sample

我们对元素进行分组并对它们进行计数,然后我们创建一个新的Array ,其中元素的数量被反转以支持较少的出现次数。 例如

arr.group_by(&:itself).transform_values{|v| arr.size / v.size}.flat_map do |k,v| 
 [k] * v
end.group_by(&:itself).transform_values(&:size)
#=> {1=>7, 3=>7, 5=>14, 6=>2, 4=>14, 7=>14}

由于5最初发生一次,现在发生14次(与4和7相同)。 因此,5,4和7具有相同的被选择的可能性,并且每次发生的可能性是1和3的两倍,其发生的次数是6次的7倍。

也许这样的事情可能更有效率

grouping =arr.group_by(&:itself).transform_values(&:size).
scale = grouping.values.uniq.reduce(&:lcm)

grouping.flat_map do |k, v|
  [k]  * (scale / v)
end.sample

如果您已经有一个用于进行随机加权选择的算法,则交换权重的一个选项可以如下所示。

grouping = ar.group_by { |n| n }.transform_values(&:size)
#=> {1=>2, 3=>2, 5=>1, 6=>7, 4=>1, 7=>1}
weights = grouping.values.uniq.sort
#=> [1, 2, 7]
reverse_mapping = weights.zip(weights.reverse).to_h
#=> {1=>7, 2=>2, 7=>1}
grouping.transform_values{ |v| reverse_mapping[v] }
#=> {1=>2, 3=>2, 5=>7, 6=>1, 4=>7, 7=>7}

这就是主意。


可以重构为更多Rubyish:

 res = ar.group_by { |n| n }.transform_values(&:size).then do |h| rev_map = h.values.uniq.sort.then { |w| w.zip(w.reverse).to_h } h.transform_values{ |v| rev_map[v] } end #=> {1=>2, 3=>2, 5=>7, 6=>1, 4=>7, 7=>7} 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM