class WeightedTable
This class contains objects and associate weights to them. So that you can sample the object according to their weights.
@author Cédric ZUGER
Constants
- BASE_WEIGHT
Public Class Methods
Read the table from a file @param filename [String] the filename from which to read the table
# File lib/weighted_table.rb, line 94 def self.from_file( filename ) YAML.load_file( filename ) end
Load a WeightedTable
with data Data format must be : [ data, data, data ] Example : [ :foo, :foo, :bar ]
@return [WeightedTable] the current WeightedTable
# File lib/weighted_table.rb, line 59 def self.from_flat_table( table ) from_weighted_table( table.group_by{ |e| e }.map{ |k, v| [ v.count, k ] } ) end
Load a WeightedTable
with data Data format must be : [ [ weight, data ], [ weight, data ], … ] Example : [ [ 2, :foo ], [ 1, :bar ] ]
@return [WeightedTable] the current WeightedTable
# File lib/weighted_table.rb, line 23 def self.from_weighted_table( table ) WeightedTable.new.from_weighted_table( table ) end
Initialize a WeightedTable
setting floating_points to true indicate that you will work with floating points rather than integers.
# File lib/weighted_table.rb, line 12 def initialize( floating_points: false ) @weights = [] @max_weight = BASE_WEIGHT @floating_points = floating_points end
Public Instance Methods
Load a WeightedTable
with data Data format must be : [ [ weight, data ], [ weight, data ], … ] Example : [ [ 2, :foo ], [ 1, :bar ] ]
@return [WeightedTable] the current WeightedTable
# File lib/weighted_table.rb, line 32 def from_weighted_table( table ) raise 'Table must contain at least one element' if table.empty? # We may call this method many time for an existing object, so we must clear it @weights.clear base = BASE_WEIGHT w = nil table.each do |weight, data| w = base + weight @weights << [base, w, data] base = w end @max_weight = w # p @weights, @max_weight self end
Return a random item from a WeightedTable
@return [Object] a random object given at the building of the table.
# File lib/weighted_table.rb, line 66 def sample # ... means that @max_weight is excluded if @floating_points r = Kernel.rand( 0.0...@max_weight.to_f ) else r = Kernel.rand( 0...@max_weight ) end # p r @weights.each do |base_weight, max_weight, data| return data if r >= base_weight && r < max_weight end raise 'Rand not in key range' end
Save the table to a file @param filename [String] the filename where to save the table
# File lib/weighted_table.rb, line 86 def to_file( filename ) File.open( filename, 'w' ) do |f| f.write( to_yaml ) end end