使用随机电话号码生成器获取错误的位数

时间:2018-03-24 01:54:27

标签: ruby

我使用以下内容生成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" 

我做错了什么?

2 个答案:

答案 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.samplerand(10),甚至是更好的解决方案:

Array.new(10) { rand(10) }