如何在Ruby中生成随机字符串

时间:2020-03-06 14:19:13  来源:igfitidea点击:

我目前正在为" 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 &lt;&lt; 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的随机字符串。它不是非常可定制的,但是又短又干净。