【发布时间】:2010-09-07 06:24:49
【问题描述】:
另外,如何将其格式化为用零填充的字符串?
【问题讨论】:
另外,如何将其格式化为用零填充的字符串?
【问题讨论】:
使用表达式“10 的 10 次方”的结果生成数字 call rand
rand(10 ** 10)
要使用零填充数字,您可以使用字符串格式运算符
'%010d' % rand(10 ** 10)
或者字符串的rjust方法
rand(10 ** 10).to_s.rjust(10,'0')
【讨论】:
0000000000。有什么办法可以防止吗?
我想贡献一个我知道的最简单的解决方案,这是一个非常好的技巧。
rand.to_s[2..11]
=> "5950281724"
【讨论】:
rand 可能会返回一个低至0.0 的浮点值,结果字符串将是"0"。如果您想确认,请在irb 中通过运行(0.0).to_s[2..11] 尝试此操作。
这是一种快速生成 10 位数字字符串的方法:
10.times.map{rand(10)}.join # => "3401487670"
【讨论】:
Array.new(10) { rand(10) }
最直接的答案可能是
rand(1e9...1e10).to_i
需要to_i 部分,因为1e9 和1e10 实际上是浮点数:
irb(main)> 1e9.class
=> Float
【讨论】:
puts Benchmark.measure{(1..1000000).map{rand(1e9...1e10).to_i}} 我实际上需要一个字符串作为我的最终结果,但即使在最后添加 .to_s 仍然会产生更快的结果。 puts Benchmark.measure{(1..1000000).map{rand(1e9...1e10).to_i.to_s}}
10000.times.map{rand(1e9...1e10).to_i.to_s}.select!{|x| x.start_with?("0")} 产生 []
rand.to_s[2..11].to_i
为什么?因为这就是你能得到的:
rand.to_s[2..9] #=> "04890612"
然后:
"04890612".to_i #=> 4890612
注意:
4890612.to_s.length #=> 7
这不是你所期望的!
要在您自己的代码中检查该错误,而不是 .to_i,您可以像这样包装它:
Integer(rand.to_s[2..9])
很快就会发现:
ArgumentError: invalid value for Integer(): "02939053"
所以最好坚持.center,但请记住:
rand(9)
有时可能会给你0。
为了防止这种情况:
rand(1..9)
它总是会返回 1..9 范围内的东西。
我很高兴我有很好的测试,我希望你不会破坏你的系统。
【讨论】:
使用Kernel#rand方法:
rand(1_000_000_000..9_999_999_999) # => random 10-digits number
使用times + map + join 组合:
10.times.map { rand(0..9) }.join # => random 10-digit string (may start with 0!)
使用String#%方法:
"%010d" % 123348 # => "0000123348"
使用KeePass password generator库,支持不同模式生成随机密码:
KeePass::Password.generate("d{10}") # => random 10-digit string (may start with 0!)
可以在 here 找到 KeePass 模式的文档。
【讨论】:
仅仅因为没有提及,Kernel#sprintf 方法(或Powerpack Library 中的别名Kernel#format)通常优于String#% 方法,如Ruby Community Style Guide 中所述。
当然,这值得商榷,但为了提供见解:
@quackingduck 答案的语法是
# considered bad
'%010d' % rand(10**10)
# considered good
sprintf('%010d', rand(10**10))
这种偏好的性质主要是由于% 的神秘性质。它本身不是很语义化,如果没有任何额外的上下文,它可能会与 % 模运算符混淆。
来自Style Guide的示例:
# bad
'%d %d' % [20, 10]
# => '20 10'
# good
sprintf('%d %d', 20, 10)
# => '20 10'
# good
sprintf('%{first} %{second}', first: 20, second: 10)
# => '20 10'
format('%d %d', 20, 10)
# => '20 10'
# good
format('%{first} %{second}', first: 20, second: 10)
# => '20 10'
为了为String#% 伸张正义,我个人非常喜欢使用类似运算符的语法而不是命令,就像使用your_array << 'foo' 而不是your_array.push('123') 一样。
这只是说明了社区中的一种趋势,什么是“最好的”取决于你。
this blogpost 中的更多信息。
【讨论】:
【讨论】:
这是一个表达式,它使用的方法调用比 quackingduck 的示例少。
'%011d' % rand(1e10)
需要注意的是,1e10 是Float,而Kernel#rand 最终会在其上调用to_i,因此对于某些更高的值,您可能会遇到一些不一致的情况。为了更准确地使用文字,您还可以这样做:
'%011d' % rand(10_000_000_000) # Note that underscores are ignored in integer literals
【讨论】:
我只想修改第一个答案。 rand (10**10) 可能会生成 9 位随机数,如果 0 在第一位。为了确保 10 个精确的数字,只需修改
code = rand(10**10)
while code.to_s.length != 10
code = rand(11**11)
结束
【讨论】:
尝试使用 SecureRandom ruby 库。
它生成随机数,但长度不具体。
通过此链接了解更多信息:http://ruby-doc.org/stdlib-2.1.2/libdoc/securerandom/rdoc/SecureRandom.html
【讨论】:
10.times.map{ SecureRandom.random_number(9)}.join
10.times.map... SecureRandom.random_number(10**10).to_s 快了大约 25%
生成n位随机数的最简单方法-
Random.new.rand((10**(n - 1))..(10**n))
生成 10 位数字号码 -
Random.new.rand((10**(10 - 1))..(10**10))
【讨论】:
(10**(10 - 1))...(10**10),因为范围结束是一个 11 位数字,并且包含在使用 .. 作为范围运算符时的范围内。
('%010d' % rand(0..9999999999)).to_s
或
"#{'%010d' % rand(0..9999999999)}"
【讨论】:
这种技术适用于任何“字母”
(1..10).map{"0123456789".chars.to_a.sample}.join
=> "6383411680"
【讨论】:
在下面直接使用即可。
rand(10 ** 9...10 ** 10)
只需在 IRB 上测试它。
(1..1000).each { puts rand(10 ** 9...10 ** 10) }
【讨论】:
rand(9999999999).to_s.center(10, rand(9).to_s).to_i
比
快rand.to_s[2..11].to_i
你可以使用:
puts Benchmark.measure{(1..1000000).map{rand(9999999999).to_s.center(10, rand(9).to_s).to_i}}
和
puts Benchmark.measure{(1..1000000).map{rand.to_s[2..11].to_i}}
在 Rails 控制台中确认。
【讨论】:
另一个答案,使用regexp-examples ruby gem:
require 'regexp-examples'
/\d{10}/.random_example # => "0826423747"
这种方法不需要“用零填充”,因为您会立即生成String。
【讨论】:
要生成一个随机的 10 位字符串:
# This generates a 10-digit string, where the
# minimum possible value is "0000000000", and the
# maximum possible value is "9999999999"
SecureRandom.random_number(10**10).to_s.rjust(10, '0')
下面是正在发生的事情的更多细节,通过将单行分成多行并带有解释变量来显示:
# Calculate the upper bound for the random number generator
# upper_bound = 10,000,000,000
upper_bound = 10**10
# n will be an integer with a minimum possible value of 0,
# and a maximum possible value of 9,999,999,999
n = SecureRandom.random_number(upper_bound)
# Convert the integer n to a string
# unpadded_str will be "0" if n == 0
# unpadded_str will be "9999999999" if n == 9_999_999_999
unpadded_str = n.to_s
# Pad the string with leading zeroes if it is less than
# 10 digits long.
# "0" would be padded to "0000000000"
# "123" would be padded to "0000000123"
# "9999999999" would not be padded, and remains unchanged as "9999999999"
padded_str = unpadded_str.rjust(10, '0')
【讨论】:
这甚至适用于 ruby 1.8.7:
rand(9999999999).to_s.center(10, rand(9).to_s).to_i
【讨论】:
更好的方法是使用Array.new() 而不是.times.map。 Rubocop 推荐它。
例子:
string_size = 9
Array.new(string_size) do
rand(10).to_s
end
Rubucop,TimesMap:
https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Performance/TimesMap
【讨论】:
(Array.new(string_size) { rand(10).to_s }).join
在我的案例中,编号在我的模型中必须是唯一的,所以我添加了检查块。
module StringUtil
refine String.singleton_class do
def generate_random_digits(size:)
proc = lambda{ rand.to_s[2...(2 + size)] }
if block_given?
loop do
generated = proc.call
break generated if yield(generated) # check generated num meets condition
end
else
proc.call
end
end
end
end
using StringUtil
String.generate_random_digits(3) => "763"
String.generate_random_digits(3) do |num|
User.find_by(code: num).nil?
end => "689"(This is unique in Users code)
【讨论】:
我做了这样的事情
x = 10 #Number of digit
(rand(10 ** x) + 10**x).to_s[0..x-1]
【讨论】:
随机 10 个数字:
require 'string_pattern'
puts "10:N".gen
【讨论】: