WeightedList attempts to improve on the very popular weighted_randomizer gem, by:
-
Sampling without replacement, analogous to Ruby's own
Array#sample
-
Implementing a weighted shuffle
-
Accepting an external source of randomness for easy deterministic testing
-
Behaving like other Ruby collections with
#each
,#map
,#sort
, etc...
Installation
Add this line to your application's Gemfile:
gem 'weighted_list'
And then execute:
$ bundle
Or install it yourself as:
$ gem install weighted_list
Usage
collection = { eastern: 150, central: 92, mountain: 21, pacific: 53 }
# This works too:
# collection = [[:eastern, 150], [:central, 92], [:mountain, 21], [:pacific, 53]]
list = WeightedList[collection]
# If you are familiar with Array#sample, none of this will surprise you:
list.sample # => :pacific
list.sample(1) # => [:central]
list.sample(3) # => [:central, :eastern, :pacific]
list.sample(100) # => [:central, :eastern, :pacific, :mountain]
# It acts like a proper Ruby collection should:
list.map(&:to_s).map(&:capitalize).sort.join(', ') # => "Central, Eastern, Mountain, Pacific"
# For when you'd like to provide your own entropy (perhaps for deterministic tests):
# Just make sure the object you pass responds to `rand`
class CustomRandomizer
def rand(n)
1.0
end
end
list.sample(2, random: CustomRandomizer.new) # => [:eastern, :central]
# If you want to allow repeats:
list.sample(4, with_replacement: true) # => [:eastern, :mountain, :eastern, :eastern]
# Shuffle the list while still respecting the weights:
list.shuffle # => [:central, :eastern, :mountain, :pacific]
list.shuffle # => [:pacific, :eastern, :central, :mountain]
list.shuffle # => [:pacific, :central, :eastern, :mountain]
# If you want to mutate the original list:
list.shuffle!
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/jaysonvirissimo/weighted_list.
License
The gem is available as open source under the terms of the MIT License.