如何在Ruby中生成随机字符串
我目前正在为" A" .." Z"生成一个8个字符的伪随机大写字符串:
value = ""; 8.times{value << (65 + rand(25)).chr}
但它看起来不干净,并且由于它不是单个语句,因此不能作为参数传递。为了获得大小写混合的字符串" a" .." z"加上" A" .." Z",我将其更改为:
value = ""; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}
但看起来像垃圾
有谁有更好的方法?
解决方案
使第一个陈述:
(0...8).collect { |n| value << (65 + rand(25)).chr }.join()
(0...8).map { (65 + rand(26)).chr }.join
我花太多时间打高尔夫球。
(0...50).map { ('a'..'z').to_a[rand(26)] }.join
最后一个更令人困惑,但更灵活,浪费的周期更少:
o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten string = (0...50).map { o[rand(o.length)] }.join
我不知道ruby,所以我不能给我们确切的语法,但是我会用可接受的字符列表设置一个常量字符串,然后使用substring运算符从中选择一个随机字符。
这样做的好处是,如果假定该字符串是用户可输入的,则可以排除容易混淆的字符,例如l和1以及i,0和O,5和S等。
这几乎是丑陋的,但也许是朝着正确方向迈出的一步?
(1..8).map{|i| ('a'..'z').to_a[rand(26)]}.join
require 'sha1' srand seed = "--#{rand(10000)}--#{Time.now}--" Digest::SHA1.hexdigest(seed)[0,8]
我们一直在代码中使用它:
class String def self.random(length=10) ('a'..'z').sort_by {rand}[0,length].join end end
支持的最大长度为25(无论如何,我们仅将其与默认值一起使用,因此这不是问题)。
有人提到,如果我们想完全避免产生令人反感的单词,则" a" .." z"不是最佳的。我们的想法之一是删除元音,但最终还是得到WTFBBQ等。
使用此方法,我们可以传递任意长度。默认设置为6.
def generate_random_string(length=6) string = "" chars = ("A".."Z").to_a length.times do string << chars[rand(chars.length-1)] end string end
我认为到目前为止,我最喜欢Radar的回答。我将进行如下调整:
CHARS = ('a'..'z').to_a + ('A'..'Z').to_a def rand_string(length=8) s='' length.times{ s << CHARS[rand(CHARS.length)] } s end
该解决方案为激活码生成了一个易于阅读的字符串。我不希望人们将B与8混淆,将I与1混淆,将O与O混淆,将L与1混淆,等等。
# Generates a random string from a set of easily readable characters def generate_activation_code(size = 6) charset = %w{ 2 3 4 6 7 9 A C D E F G H J K M N P Q R T V W X Y Z} (0...size).map{ charset.to_a[rand(charset.size)] }.join end
我不记得我在哪里找到的,但对我来说似乎是最好,最省力的过程:
def random_string(length=10) chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789' password = '' length.times { password << chars[rand(chars.size)] } password end
在ruby 1.9中,可以使用Array的choice方法,该方法从数组中返回随机元素
为什么不使用SecureRandom?
require 'securerandom' random_string = SecureRandom.hex # outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81 (i.e. 32 chars of 0..9, a..f)
SecureRandom还具有以下方法:
- base64
- random_bytes
- random_number
参见:http://ruby-doc.org/stdlib-1.9.2/libdoc/securerandom/rdoc/SecureRandom.html
我喜欢使用的另一种方法
rand(2**256).to_s(36)[0..7]
如果我们对正确的字符串长度确实有些偏执,请添加ljust:
rand(2**256).to_s(36).ljust(8,'a')[0..7]
`pwgen 8 1`.chomp
Ruby 1.9+:
ALPHABET = ('a'..'z').to_a #=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] 10.times.map { ALPHABET.sample }.join #=> "stkbssowre" # or 10.times.inject('') { |s| s + ALPHABET.sample } #=> "fdgvacnxhc"
我最近在做这样的事情,从62个字符中生成了一个8字节的随机字符串。字符为0-9,a-z,A-Z。我有一个数组,循环了8次,并从数组中选择了一个随机值。这是在Rails应用程序内。
str ='' 8.次{| i | str << ARRAY_OF_POSSIBLE_VALUES [rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)]}
奇怪的是,我得到了很多重复的东西。现在,这几乎永远不会发生。 62 ^ 8很大,但是在数据库中的1200个左右的代码中,我有很多重复项。我注意到它们发生在彼此的小时边界上。换句话说,我可能会在12:12:23和2:12:22看到类似的情况……不确定时间是否是问题所在。
这段代码在创建activerecord对象之前。在创建记录之前,此代码将运行并生成"唯一"代码。 db中的条目始终可靠地生成,但是代码(上一行的str)被复制得太多了。
我创建了一个脚本来运行上述行的100000次迭代,并且延迟很小,因此需要3-4个小时才能希望每小时看到某种重复模式,但什么也没看到。我不知道为什么这会在我的Rails应用程序中发生。
我用它来生成具有最大长度保证的随机URL友好字符串:
rand(36**length).to_s(36)
它生成小写字母a-z和0-9的随机字符串。它不是非常可定制的,但是又短又干净。