Class: WeightedTable

Inherits:
Object
  • Object
show all
Defined in:
lib/weighted_table.rb

Overview

This class contains objects and associate weights to them. So that you can sample the object according to their weights.

Author:

  • Cédric ZUGER

Constant Summary collapse

BASE_WEIGHT =
0

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(floating_points: false) ⇒ WeightedTable

Initialize a WeightedTable setting floating_points to true indicate that you will work with floating points rather than integers.



12
13
14
15
16
# File 'lib/weighted_table.rb', line 12

def initialize( floating_points: false )
  @weights = []
  @max_weight = BASE_WEIGHT
  @floating_points = floating_points
end

Class Method Details

.from_file(filename) ⇒ Object

Read the table from a file

Parameters:

  • filename (String)

    the filename from which to read the table



94
95
96
# File 'lib/weighted_table.rb', line 94

def self.from_file( filename )
  YAML.load_file( filename )
end

.from_flat_table(table) ⇒ WeightedTable

Load a WeightedTable with data Data format must be : [ data, data, data ] Example : [ :foo, :foo, :bar ]

Returns:



59
60
61
# 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

.from_weighted_table(table) ⇒ WeightedTable

Load a WeightedTable with data Data format must be : [ [ weight, data ], [ weight, data ], … ] Example : [ [ 2, :foo ], [ 1, :bar ] ]

Returns:



23
24
25
# File 'lib/weighted_table.rb', line 23

def self.from_weighted_table( table )
  WeightedTable.new.from_weighted_table( table )
end

Instance Method Details

#from_weighted_table(table) ⇒ WeightedTable

Load a WeightedTable with data Data format must be : [ [ weight, data ], [ weight, data ], … ] Example : [ [ 2, :foo ], [ 1, :bar ] ]

Returns:



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 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

#sampleObject

Return a random item from a WeightedTable

Returns:

  • (Object)

    a random object given at the building of the table.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 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

#to_file(filename) ⇒ Object

Save the table to a file

Parameters:

  • filename (String)

    the filename where to save the table



86
87
88
89
90
# File 'lib/weighted_table.rb', line 86

def to_file( filename )
  File.open( filename, 'w' ) do |f|
    f.write( to_yaml )
  end
end