我使用以下内容生成10个随机数字:
10.times.map {|i| (0...9).to_a[rand(10)] }.join
但如果你运行它,你会发现它不会给你10个随机数字。我不懂为什么。 次迭代器将运行10次:
10.times
每次调用迭代器时,我们也会将 map 调用链接到它并传递黑色。这确保了块的内容也将被调用10次:
10.times.map {|i| }
在块中,我们采用一个间隔,一组带有开头和结尾的值。在Ruby中,我们可以使用范围来完成此操作。我们采用0-9的数字范围。
(0...9)
我们在范围内调用 to_a ,该范围将获取范围内的所有元素并将它们作为索引添加到数组中。 to_a有一个类方法 [] 。这将根据传入的给定值为原始数组中的每个项返回一个新数组。
to_a[]
当max为整数时, rand 会返回一个大于或等于零且小于最大值的随机整数。我们使用rand生成新值。
rand
由于10次被调用10次,我们应该在0到9之间有10个随机数字,包括0和9。我们只是使用join将它们组合在一起:
join
然而我跑了这个并没有给我10个数字:
10.times.map {|i| (0...9).to_a[rand(10)] }.join
=> "151063260"
我做错了什么?
答案 0 :(得分:2)
每当你执行(0...9).to_a[rand(10)]
时,rand(10)
返回9,并且0...9
范围内没有9,这就是为什么你得到一些零值,这是最终的从join
生成的字符串中“删除”。
一个例子可能是:
p 10.times.map {|i| (0...9).to_a[rand(10)] }
# [6, 6, 7, 1, 1, 1, nil, 1, nil, 7]
你有两个零值,然后“消失”,因为在一个nil对象中应用to_s
的结果是一个空字符串""
:
p [6, 6, 7, 1, 1, 1, nil, 1, nil, 7].join
"66711117"
最简单的修复方法是将rand参数更改为10,将其返回的最大值设为9,将范围内的最大值更改为(0..9):
10.times.map { (0..9).to_a[rand(10)] }.join # Omitted the block variable
虽然注意到你可以使用样本获得相同的方法:
10.times.map { (0..9).to_a.sample }
甚至更好的Array.new带块:
Array.new(10) { rand(10) }
至少树的实现方式在可见的时间内有所不同,因此您可以选择(当然还有更多):
rand 1.340000 0.020000 1.360000 ( 1.368701) # 10.times.map { (0..9).to_a[rand(10)] }
sample 1.170000 0.020000 1.190000 ( 1.194385) # 10.times.map { (0..9).to_a.sample }
Array.new 0.250000 0.000000 0.250000 ( 0.253762) # Array.new(10) { rand(10) }
(使用超过100000次迭代的基准测试)
答案 1 :(得分:2)
根据docs:
使用..构建的范围包括从开始到结束。使用...创建的那些排除了最终值..
所以a..b
就像a <= x <= b
,而a...b
就像a <= x < b
,即:
(0...9).to_a # => [0, 1, 2, 3, 4, 5, 6, 7, 8]
rand(10)
将从0
返回9
。如果它返回9
,则块内的命令将返回nil
[0, 1, 2, 3, 4, 5, 6, 7, 8][9] # => nil
[0, 1, 2, 3, 4, 5, 6, 7, 8, nil].join # => '012345678'
为了解决您的问题,您可以在块中使用(0..9).to_a.sample
或rand(10)
,甚至是更好的解决方案:
Array.new(10) { rand(10) }