Ruby 生成随机字符串的一行代码

fleuria · 2012年07月08日 · 最后由 zach777 回复于 2015年05月27日 · 12370 次阅读

昨天不小心在 stackoverflow 看到的,很有趣:

def random_str(len)
  rand(36**len).to_s 36
end

update: 经 @fcicq 君提醒,这个算法有个问题。大家想想修补的方法吧 :D

有什么问题?

是不是位数不够?

我都是用 SecureRandom 模块的方法的。

> SecureRandom.hex 32
=> "3b47b9639b0da4592a008d58eaf6cbf0894655a73b63874cf6204914a466ff5c"

('a'..'z').to_a.shuffle[0..7].join

#1 楼 @chucai 如 2 楼 Rei 说的,位数不够,有一定概率会返回小于 len 长度的字符串

#2 楼 @Rei #3 楼 @Teddy 学习了,多谢! ^

def random_str(len) rand(36*(len - 1) ... 36*len).to_s 36 end

p (Array.new(10) { 97 + rand(26).to_i }).pack "c*"

@fcicq ....又见@fcicq ....每隔两年都会在一个不同语言的论坛看到@fcicq ........

#4 楼 @fleuria 谢谢,难怪。我以前一个项目用过这个方法 出现过一次 位数不够的情况 当时没有注意 :(

哈, 相当不靠谱啊.

我执行了 100 次生成10000个10位数的密码的操作, 最后结果没有达到 10 位的结果如下:

275
280
285
306
285
282
260
290
314
289
262
260
305
277
260
235
274
289
258
262
292
288
294
273
304
286
254
279
286
296
293
261
287
295
267
260
270
266
276
276
319
275
294
268
282
288
300
297
252
267
276
299
270
285
281
287
304
288
275
284
291
263
287
279
309
255
271
255
270
283
309
296
266
287
292
284
298
276
275
263
250
281
262
289
306
253
280
255
289
247
276
278
257
268
246
262
262
290
287
270

这机率应该算是挺高了吧.

刚刚测试了另一个应该是 20 位的密码字串. Array.new(10) { rand(1295).to_s(36) }.join

还不如楼主的呢. 10000 里面就有两千多个不够 20 位.

#10 楼 @zw963 rand 位数有变动,用 rand(Range) 应该可以,但是不知道应该是几位

#6 楼 @jjym

代码是错的. 怎么可以花括号前的参数不加括号呢?

#11 楼 @jjym

事实上是, 如果那个数值小于 36 的话, 只能生成一个英文或数字. Array.new(10) { rand(36..1295).to_s(36) }.join 就没问题了.

def random_str(len)
  rand(36**(len-1)..36**(len)).to_s 36
end

这可以保证总是 len 位数, 不过貌似限定了范围, 就没那么随机了...

#14 楼 @zw963 我是不知道 to_s(36) 是什么意思才这样写的....

#15 楼 @jjym

貌似好多人都不知道. 呵呵, 针对 Fixnum 实现了 to_s 方法, 可以将一个十进制的数字转化为其他进制.

例如: 10.to_s(2) # => "1010"

多两行可以解决 len 不固定这个问题 def generate_rand_password passwd_len arr = [] passwd_len.times {arr << rand(36).to_s(36)} arr.join("") end

需要 登录 后方可回复, 如果你还没有账号请 注册新账号