require 'active_support/core_ext/enumerable' module WeightedShuffle class Dealer < Struct.new(:array) def weighted_shuffle(options = {}) factor = options.delete(:factor) a = Marshal.load Marshal.dump(array) unless factor.nil? a.map! { |k, v| [k, v**factor] } end sum = a.sum { |k, v| v || 0.0 } b = [] a.length.times do random = SecureRandom.random_number * sum a.each_with_index do |(k, v), j| if random <= v b << a.delete_at(j).first sum -= v break else random -= v end end end b end end end