[フレーム]
Last Updated: November 18, 2020
·
4.155K
· janlelis

Array#sample and Array#shuffle using SecureRandom

Encourages you to use SecureRandom more often. Don't use srand!

USAGE

$ gem install securerandom-array
$ irb
>> require 'securerandom/array'
>> [1,2,3].secure_shuffle # e.g. [1,3,2]
>> [1,2,3].secure_sample # e.g. 2
>> [1,2,3].secure_sample(random: Random.new(42)) # => 2

CODE

require 'securerandom'

class Array
 # Has a similar API like #shuffle, but uses SecureRandom
 # Delegates to original #shuffle if a Hash argument is given
 def secure_shuffle(o={})
 raise ArgumentError, 'wrong number of arguments (1 for 0)' unless o.is_a?(Hash)
 if random = o[:random]
 shuffle(random: random)
 else
 old = dup
 [*1..size].reverse_each.with_object([]){ |i, res|
 res << old.delete_at(SecureRandom.random_number(i))
 }
 end
 end

 # Has a similar API like #sample, but uses SecureRandom
 # Delegates to original #sample if a Hash argument is given
 def secure_sample(n=:single, o={})
 o, n = n, :single if n.is_a?(Hash)
 raise ArgumentError, 'wrong number of arguments (2 for 1)' unless o.is_a?(Hash)
 if random = o[:random]
 args = [{random: random}]
 args.unshift(n) unless n == :single
 sample(*args)
 else
 if n == :single
 self[SecureRandom.random_number(size)]
 else
 raise ArgumentError, 'negative sample number' if n < 0
 res = []
 old = dup
 n = size if n > size
 [*(size-n+1)..size].reverse_each.with_object([]){ |i, res|
 res << old.delete_at(SecureRandom.random_number(i))
 }
 end
 end
 end

end

2 Responses
Add your response

Can you please publish this gem on Github?

over 1 year ago ·

Can't you just do:

[1,2,3].shuffle(random: SecureRandom)
over 1 year ago ·

AltStyle によって変換されたページ (->オリジナル) /