随机项目的重量

例如,我有这些数据:

headings = { :heading1 => { :weight => 60, :show_count => 0} :heading2 => { :weight => 10, :show_count => 0} :heading3 => { :weight => 20, :show_count => 0} :heading4 => { :weight => 10, :show_count => 0} } total_views = 0 

现在我想根据他们的体重为每个标题服务。 例如,对于前10个请求/迭代, heading1heading3heading2heading4将按顺序(按重量)分别提供heading4和1次。

对于每次迭代,服务标题的show_count将递增1,total_views也将全局递增。

你能建议一个算法或一些ruby代码来处理这个问题。

这应该适用于您的基本情况,可以根据您需要的细节进行修改:

  class Heading attr_reader :heading, :weight, :show_count def initialize(heading,weight=1) @heading=heading @weight=weight @show_count=0 end def serve puts "Served #{@heading}! " @show_count += 1 end end class HeadingServer attr_reader :headings def initialize(headings_hash) @headings=headings_hash.map {|h, data| Heading.new(h,data[:weight])} @total_weight=@headings.inject(0) {|s,h| s+= h.weight} end def serve(num_to_serve=@total_weight) @headings.sort {|a,b| b.weight <=> a.weight}.each do |h| n = (h.weight * num_to_serve) / @total_weight #possibility of rounding errors n.times { h.serve } end end def total_views @headings.inject(0) {|s,h| s += h.show_count} end end headings = { :heading1 => { :weight => 60, :show_count => 0}, :heading2 => { :weight => 10, :show_count => 0}, :heading3 => { :weight => 20, :show_count => 0}, :heading4 => { :weight => 10, :show_count => 0} } # Example Usage: hs = HeadingServer.new(headings) hs.serve(10) hs.headings.each {|h| puts "#{h.heading} : served #{h.show_count} times"} puts "Total Views: #{hs.total_views}" 

你可以使用皮卡gem

它接受这样的哈希:

 require 'pickup' headings = { heading1: 60, heading2: 10, heading3: 20, heading4: 10 } pickup = Pickup.new(headings) pickup.pick #=> heading1 pickup.pick #=> heading1 pickup.pick #=> heading3 pickup.pick #=> heading1 pickup.pick #=> heading4 

所以你可以这样做:

 require 'pickup' headings = { heading1: { :weight => 60, :show_count => 0}, heading2: { :weight => 10, :show_count => 0}, heading3: { :weight => 20, :show_count => 0}, heading4: { :weight => 10, :show_count => 0} } pickup_headings = headings.inject({}){ |h, (k,v)| h[k] = v[:weight]; h} pickup = Pickup.new(pickup_headings) # let's fire it 1000 times 1000.times do server = pickup.pick headings[server][:show_count] += 1 end puts headings #=> { #=> :heading1=>{:weight=>60, :show_count=>601}, #=> :heading2=>{:weight=>10, :show_count=>116}, #=> :heading3=>{:weight=>20, :show_count=>176}, #=> :heading4=>{:weight=>10, :show_count=>107} #=> }