Class: Splashy::Buckets
- Inherits:
-
Object
- Object
- Splashy::Buckets
- Defined in:
- lib/splashy/buckets.rb
Instance Method Summary collapse
-
#add(bucket_name, element) ⇒ Object
Public: Add a single element to a bucket.
-
#fill(bucket_name = nil, &block) ⇒ Object
Public: Put elements into buckets with a block.
-
#initialize(wanted_distribution, wanted_count = nil) ⇒ Buckets
constructor
wanted_distribution - A Hash of desired distributions: { :a => 0.2, :b => 0.5, :c => 0.3 } wanted_count - (optional) Maximum total elements to be selected.
-
#neediest_buckets ⇒ Object
Array of the buckets that need more elements to match the desired distribution, sorted descending by how much more they need.
-
#satisfied? ⇒ Boolean
Public.
-
#select(opts = {}) ⇒ Object
Public: Return a distribution of elements based on the desired distribution.
Constructor Details
#initialize(wanted_distribution, wanted_count = nil) ⇒ Buckets
wanted_distribution - A Hash of desired distributions:
{ :a => 0.2, :b => 0.5, :c => 0.3 }
wanted_count - (optional) Maximum total elements to be selected.
otherwise, the maximum size set is selected.
7 8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/splashy/buckets.rb', line 7 def initialize( wanted_distribution, wanted_count=nil ) unless wanted_distribution.values.inject(0){ |m,v| m + v } == 1.0 raise ArgumentError.new( "Distribution must sum to 1.0" ) end @wanted_distribution = wanted_distribution @wanted_count = wanted_count @buckets = {} @wanted_distribution.keys.each do |bucket_name| @buckets[bucket_name] = Bucket.new( bucket_name ) end @total_count = 0 end |
Instance Method Details
#add(bucket_name, element) ⇒ Object
Public: Add a single element to a bucket.
45 46 47 48 49 50 51 |
# File 'lib/splashy/buckets.rb', line 45 def add( bucket_name, element ) unless @wanted_distribution[bucket_name] raise ArgumentError.new( "#{bucket_name.inspect} is not a valid bucket." ) end @buckets[bucket_name] << element @total_count += 1 end |
#fill(bucket_name = nil, &block) ⇒ Object
Public: Put elements into buckets with a block.
bucket_name - If supplied, all yielded elements will be added to that
bucket.
&block - A block that returns (if ‘bucket_name` is not supplied) an
Array: [bucket_name, element]. If `bucket_name` is supplied, only
the element needs to be returned.
Examples
fill { return [bucket_name, element] }
fill( :bucket_name ) { return element }
32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/splashy/buckets.rb', line 32 def fill( bucket_name = nil, &block ) if bucket_name while element = yield( @total_count ) self.add( bucket_name, element ) end else while pair = yield( @total_count ) self.add( *pair ) end end end |
#neediest_buckets ⇒ Object
Array of the buckets that need more elements to match the desired distribution, sorted descending by how much more they need.
85 86 87 88 89 |
# File 'lib/splashy/buckets.rb', line 85 def neediest_buckets multipliers = self.needed_multipliers( self._select_all, @wanted_distribution ).to_a multipliers.sort! { |a, b| b[1] <=> a[1] } # Sort on multiplier descending multipliers.map{ |bucket_name, multiplier| bucket_name } end |
#satisfied? ⇒ Boolean
Public
Returns true if the conditions (distribution and, optionally, count) are satisfied enough to do a final selection of elements.
57 58 59 60 61 62 63 64 |
# File 'lib/splashy/buckets.rb', line 57 def satisfied? begin self.assert_satisfied! true rescue DistributionUnsatisfiedError => e false end end |
#select(opts = {}) ⇒ Object
Public: Return a distribution of elements based on the desired distribution. If a satisfactory distribution is not possible, a DistributionUnsatisfiedError is raised.
Returns a Hash of elements matching the desired distribution, keyed by the bucket names.
72 73 74 75 76 77 78 79 80 81 |
# File 'lib/splashy/buckets.rb', line 72 def select( opts = {} ) self.assert_satisfied! opts = { :random => false }.merge( opts ) selected = self._select_wanted( opts[:random] ) # Sometimes we need to fudge by a few to meet the `@wanted_count` selected = self.trim( selected, @wanted_count ) if @wanted_count selected end |