【问题标题】:Getting wrong number of digits with my random phone number generator使用我的随机电话号码生成器获取错误的位数
【发布时间】:2018-03-24 01:54:27
【问题描述】:

我正在使用以下方法生成 10 个随机数字:

10.times.map {|i| (0...9).to_a[rand(10)] }.join

但是如果你运行它,你会注意到它没有给你 10 个随机数字。我不明白为什么。 times 迭代器将运行 10 次:

10.times

对于每次调用迭代器,我们还将 ma​​p 调用链接到它并传递一个黑色。这样可以确保块的内容也会被调用 10 次:

10.times.map {|i| }

在块内部,我们采用一个区间,即一组具有开头和结尾的值。在 Ruby 中,我们可以使用 range 来做到这一点。我们取从 0 到 9 的数字范围。

(0...9)

我们在范围上调用 to_a,它将获取范围内的所有元素并将它们作为索引粘贴到数组中。 to_a 有一个类方法[]。这会根据传入的给定值为原始数组中的每个项目返回一个新数组。

to_a[]

当 max 为 Integer 时,rand 返回一个大于或等于 0 且小于 max 的随机整数。我们使用 rand 来生成我们的新值。

rand

由于 10.times 被调用了 10 次,我们应该有 10 个介于 0 和 9 之间的随机数字,包括 0 和 9。我们只是在最后使用 join 来组合它们:

join

但我运行它并没有给我 10 个数字:

10.times.map {|i| (0...9).to_a[rand(10)] }.join
 => "151063260" 

我做错了什么?

【问题讨论】:

  • 附带说明,我还使用 insert 来添加连字符:str.insert(3,"-")
  • 这里的关键是...不包括在内,但..是包括在内。

标签: ruby


【解决方案1】:

每当你执行(0...9).to_a[rand(10)] 时,rand(10) 返回 9 的概率,而在0...9 范围内没有 9,这就是为什么你会得到一些 nil 值,这些值最终会从字符串中“删除” join 生成。

一个例子可以是:

p 10.times.map {|i| (0...9).to_a[rand(10)] }
# [6, 6, 7, 1, 1, 1, nil, 1, nil, 7]

那里有两个 nil 值,然后它们“消失”,因为在 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 次迭代的基准测试)

【讨论】:

  • (0...10).to_a.shuffle 将始终生成唯一编号。 (0...9).to_a.samplerand(9) 将错过号码 9
  • 当然。已编辑。谢谢。
  • 旁注:只使用rand 将是最快的,例如rand(1_000_000_000..9_999_999_999).to_s 因为构建 Array 似乎是生成字符串的中间步骤。
【解决方案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'

为了解决你的问题,你可以在你的block里面使用(0..9).to_a.sample或者rand(10),甚至是更好的解决方案:

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

【讨论】:

  • rand(0..9)
  • @SebastianPalma,谢谢。在调用sample 之前,我忘记将其转换为数组。让我更新答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 2018-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-15
相关资源
最近更新 更多