Skip to content

Commit

Permalink
array#sample adapted from rubinius
Browse files Browse the repository at this point in the history
  • Loading branch information
kostya committed Jun 30, 2013
1 parent 63448f0 commit fd6712d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 38 deletions.
46 changes: 46 additions & 0 deletions lib-topaz/array.rb
Expand Up @@ -509,6 +509,52 @@ def transpose
out
end

def sample(*args)
case args.size
when 0
return self[Kernel.rand(size)]
when 1
arg = args[0]
if o = Topaz.try_convert_type(arg, Hash, :to_hash)
options = o
count = nil
else
options = nil
count = Topaz.convert_type(arg, Fixnum, :to_int)
end
when 2
count = Topaz.convert_type(args[0], Fixnum, :to_int)
options = Topaz.convert_type(args[1], Hash, :to_hash)
else
raise ArgumentError.new("wrong number of arguments (#{args.size} for 1)")
end

raise ArgumentError.new("negative sample number") if count and count < 0

rng = options[:random] if options
rng = Kernel unless rng && rng.respond_to?(:rand)

unless count
random = Topaz.convert_type(rng.rand, Float, :to_f)
raise RangeError.new("random number too big #{random}") if random < 0 || random >= 1.0

return self[random * size]
end

count = size if count > size
out = Array.new(self)

count.times do |i|
random = Topaz.convert_type(rng.rand, Float, :to_f)
raise RangeError.new("random number too big #{random}") if random < 0 || random >= 1.0

r = (random * size).to_i
out[i], out[r] = out[r], out[i]
end

return (count == size) ? out : out[0, count]
end

def self.try_convert(arg)
Topaz.try_convert_type(arg, Array, :to_ary)
end
Expand Down
38 changes: 0 additions & 38 deletions spec/tags/core/array/sample_tags.txt

This file was deleted.

0 comments on commit fd6712d

Please sign in to comment.