这是我到目前为止:
myArray.map!{ rand(max) }
然而,显然,有时候列表中的数字并不是唯一的.如何确保我的列表只包含唯一的数字,而不必创建一个更大的列表,然后我从中选择n个唯一的数字?
编辑:
我真的很想看到这个完成w/o循环 - 如果可能的话.
(0..50).to_a.sort{ rand() - 0.5 }[0..x]
(0..50).to_a
可以用任何数组替换.0是"minvalue",50是"max value"x是"我想要多少值"
当然,x不可能大于max-min :)
在扩展这是如何工作的
(0..5).to_a ==> [0,1,2,3,4,5] [0,1,2,3,4,5].sort{ -1 } ==> [0, 1, 2, 4, 3, 5] # constant [0,1,2,3,4,5].sort{ 1 } ==> [5, 3, 0, 4, 2, 1] # constant [0,1,2,3,4,5].sort{ rand() - 0.5 } ==> [1, 5, 0, 3, 4, 2 ] # random [1, 5, 0, 3, 4, 2 ][ 0..2 ] ==> [1, 5, 0 ]
值得一提的是,当时这个问题最初Array#shuffle
是在2008年9月回答的,这个问题要么不可用,要么我不知道,因此近似于Array#sort
结果就是有一连串的建议编辑.
所以:
.sort{ rand() - 0.5 }
可以更好,更短的表达现代ruby实现使用
.shuffle
另外,
[0..x]
可以更明显地写Array#take
为:
.take(x)
因此,在现代红宝石上生成一系列随机数的最简单方法是:
(0..50).to_a.shuffle.take(x)
这使用Set:
require 'set' def rand_n(n, max) randoms = Set.new loop do randoms << rand(max) return randoms.to_a if randoms.size >= n end end
只是为了让你了解速度,我运行了四个版本:
像Ryan的建议一样使用集合.
使用比需要稍大的数组,然后执行uniq!在末尾.
使用哈希,像凯尔建议的那样.
创建一个所需大小的数组,然后随机排序,就像肯特的建议(但没有无关的" - 0.5",什么都不做).
它们都是小规模的快速,所以我让它们各自创建一个1,000,000个数字的列表.以下是时间,以秒为单位:
套装:628
Array + uniq:629
哈希:645
fixed Array + sort:8
不,最后一个不是拼写错误.因此,如果您关心速度,并且数字从0到任何整数都可以,那么我的确切代码是:
a = (0...1000000).sort_by{rand}
Ruby 1.9提供了Array#sample方法,该方法返回一个元素或从Array中随机选择的元素.#sample的结果将不包括两次相同的Array元素.
(1..999).to_a.sample 5 # => [389, 30, 326, 946, 746]
与该to_a.sort_by
方法相比,该sample
方法似乎明显更快.在一个简单的场景我比sort_by
来sample
,并得到下面的结果.
require 'benchmark' range = 0...1000000 how_many = 5 Benchmark.realtime do range.to_a.sample(how_many) end => 0.081083 Benchmark.realtime do (range).sort_by{rand}[0...how_many] end => 2.907445