diff --git a/lib-topaz/array.rb b/lib-topaz/array.rb index 9c029b08c..c1975c6f8 100644 --- a/lib-topaz/array.rb +++ b/lib-topaz/array.rb @@ -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 diff --git a/spec/tags/core/array/sample_tags.txt b/spec/tags/core/array/sample_tags.txt deleted file mode 100644 index 813ba773f..000000000 --- a/spec/tags/core/array/sample_tags.txt +++ /dev/null @@ -1,38 +0,0 @@ -fails:Array#sample selects a value from the array -fails:Array#sample returns a distribution of results -fails:Array#sample returns nil for empty arrays -fails:Array#sample passed a number n as an argument raises ArgumentError for a negative n -fails:Array#sample passed a number n as an argument selects values from the array -fails:Array#sample passed a number n as an argument does not return the same value if the array is unique -fails:Array#sample passed a number n as an argument may return the same value if the array is not unique -fails:Array#sample passed a number n as an argument returns a distribution of results -fails:Array#sample passed a number n as an argument tries to convert n to an Integer using #to_int -fails:Array#sample passed a number n as an argument returns all values when n >= array size -fails:Array#sample passed a number n as an argument returns [] for empty arrays or if n <= 0 -fails:Array#sample passed a number n as an argument does not return subclass instances with Array subclass -fails:Array#sample returns only one element -fails:Array#sample returns proper array size -fails:Array#sample attempts coercion via #to_hash -fails:Array#sample uses default random generator -fails:Array#sample uses given random generator -fails:Array#sample uses default random generator and return proper array size -fails:Array#sample uses given random generator and return proper array size -fails:Array#sample returns nil for an empty Array -fails:Array#sample returns a single value when not passed a count -fails:Array#sample returns an empty Array when passed zero -fails:Array#sample returns an Array of elements when passed a count -fails:Array#sample returns elements from the Array -fails:Array#sample returns at most the number of elements in the Array -fails:Array#sample does not return the same value if the Array has unique values -fails:Array#sample may return the same value if the array is not unique -fails:Array#sample calls #to_int to convert the count when passed an Object -fails:Array#sample raises ArgumentError when passed a negative count -fails:Array#sample does not return subclass instances with Array subclass -fails:Array#sample calls #to_hash to convert the passed Object -fails:Array#sample calls #to_int on the first argument and #to_hash on the second when passed Objects -fails:Array#sample calls #rand on the Object passed by the :random key in the arguments Hash -fails:Array#sample calls #to_f on the Object returned by #rand -fails:Array#sample raises a RangeError if the random generator returns a value less than 0.0 -fails:Array#sample raises a RangeError if the random generator returns a value equal to 1.0 -fails:Array#sample raises a RangeError if the random generator returns a value greater than 1.0 -fails:Array#sample ignores an Object passed for the RNG if it does not define #rand