Как сгенерировать случайную строку в Ruby - PullRequest
710 голосов
/ 18 сентября 2008

В настоящее время я генерирую 8-символьную псевдослучайную строку в верхнем регистре для "A" .. "Z":

value = ""; 8.times{value  << (65 + rand(25)).chr}

но он не выглядит чистым и не может быть передан в качестве аргумента, поскольку это не одно утверждение. Чтобы получить строку со смешанным регистром "a" .. "z" плюс "A" .. "Z", я изменил ее на:

value = ""; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}

но это похоже на мусор.

У кого-нибудь есть лучший метод?

Ответы [ 51 ]

923 голосов
/ 18 сентября 2008
(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
766 голосов
/ 25 октября 2009

Почему бы не использовать SecureRandom?

require 'securerandom'
random_string = SecureRandom.hex

# outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81 (i.e. 32 chars of 0..9, a..f)

SecureRandom также имеет методы для:

  • base64
  • random_bytes
  • случайное_число

см .: http://ruby -doc.org / stdlib-1.9.2 / libdoc / securerandom / rdoc / SecureRandom.html

241 голосов
/ 26 августа 2010

Я использую это для генерации случайных URL-дружественных строк с гарантированной максимальной длиной:

rand(36**length).to_s(36)

Генерирует случайные строки из строчных букв a-z и 0-9. Это не очень настраиваемый, но он короткий и чистый.

168 голосов
/ 29 января 2009

Это решение генерирует строку легко читаемых символов для кодов активации; Я не хотел, чтобы люди путали 8 с B, 1 с I, 0 с 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
125 голосов
/ 28 августа 2011

Другие упоминали что-то подобное, но при этом используется функция безопасного URL.

require 'securerandom'
p SecureRandom.urlsafe_base64(5) #=> "UtM7aa8"
p SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
p SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="

Результат может содержать A-Z, a-z, 0-9, «-» и «_». «=» Также используется, если отступ равен true.

45 голосов
/ 04 января 2012
[*('A'..'Z')].sample(8).join

Генерация случайной 8-буквенной строки (например, NVAYXHGR)

([*('A'..'Z'),*('0'..'9')]-%w(0 1 I O)).sample(8).join

Создает случайную 8-символьную строку (например, 3PH4SWF2), исключая 0/1 / I / O. Рубин 1,9

39 голосов
/ 30 января 2018

С ruby ​​2.5 действительно легко с SecureRandom.alphanumeric:

len = 8
SecureRandom.alphanumeric(len)
=> "larHSsgL"

Генерирует случайные строки, содержащие A-Z, a-z и 0-9 и, следовательно, должны применяться в большинстве случаев использования. И они генерируются случайным образом, что тоже может быть выгодно.


Редактировать: тест для сравнения с решением, имеющим наибольшее количество голосов:

require 'benchmark'
require 'securerandom'

len = 10
n = 100_000

Benchmark.bm(12) do |x|
  x.report('SecureRandom') { n.times { SecureRandom.alphanumeric(len) } }
  x.report('rand') do
    o = [('a'..'z'), ('A'..'Z'), (0..9)].map(&:to_a).flatten
    n.times { (0...len).map { o[rand(o.length)] }.join }
  end
end

                   user     system      total        real
SecureRandom   0.429442   0.002746   0.432188 (  0.432705)
rand           0.306650   0.000716   0.307366 (  0.307745)

Таким образом, решение rand занимает всего около 3/4 времени SecureRandom. Может иметь значение, если вы генерируете действительно много строк, но если вы просто время от времени создаете какую-то случайную строку, я всегда выбираю более безопасную реализацию (так как ее также проще вызывать и более явную).

30 голосов
/ 13 июля 2009

Я не могу вспомнить, где я нашел это, но мне кажется, что это лучший и наименее интенсивный процесс:

def random_string(length=10)
  chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
  password = ''
  length.times { password << chars[rand(chars.size)] }
  password
end
27 голосов
/ 13 июля 2012
require 'securerandom'
SecureRandom.urlsafe_base64(9)
24 голосов
/ 11 июля 2013

Если вы хотите строку указанной длины, используйте:

require 'securerandom'
randomstring = SecureRandom.hex(n)

Будет сгенерирована случайная строка длиной 2n, содержащая 0-9 и a-f

...