Как создать случайную строку в Ruby
в настоящее время я генерирую 8-символьную псевдослучайную строку верхнего регистра для "A" .. "Z":
value = ""; 8.times{value << (65 + rand(25)).chr}
но он не выглядит чистым, и его нельзя передать как аргумент, так как это не одно утверждение. Чтобы получить строку со смешанным регистром "a".. "з" плюс "а".. "Z", я изменил его на:
value = ""; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}
но это выглядит как мусор.
у кого-нибудь есть лучше способ?
30 ответов
(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
почему бы не использовать 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
Я использую это для генерации случайных дружественных строк URL с гарантированной максимальной длиной:
rand(36**length).to_s(36)
Он генерирует случайные строки в нижнем регистре a-z и 0-9. Он не очень настраиваемый, но он короткий и чистый.
Это решение генерирует строку легко читаемых символов для кодов активации; я не хотел, чтобы люди путали 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
другие упоминали что-то подобное, но это использует функцию url safe.
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.
[*('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. Ruby 1.9
Я не могу вспомнить, где я это нашел, но мне кажется, что это лучший и наименее интенсивный процесс:
def random_string(length=10)
chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
password = ''
length.times { password << chars[rand(chars.size)] }
password
end
так как ruby 2.5 очень легко с SecureRandom.alphanumeric
:
len = 8
SecureRandom.alphanumeric(len)
=> "larHSsgL"
генерирует случайные строки, содержащие A-Z, a-z и 0-9 и поэтому должны применяться в большинстве случаев использования. И они генерируются случайным образом безопасно, что может быть полезным, тоже.
Edit: бенчмарк, чтобы сравнить его с решением, имеющим большинство upvotes:
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
. Может иметь значение, если вы генерируйте действительно много строк, но если вы просто создаете некоторую случайную строку время от времени, я всегда буду идти с более безопасной реализацией (так как ее также легче вызвать и более явной).
если вы хотите строку указанной длины, используйте:
require 'securerandom'
randomstring = SecureRandom.hex(n)
Он будет генерировать случайную строку длиной 2n
С 0-9
и a-f
Array.new(n){[*"0".."9"].sample}.join
,
где N=8 в вашем случае.
обобщенно: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join
, etc. - от этой ответ
вот одна строка простого кода для случайной строки длиной 8
random_string = ('0'..'z').to_a.shuffle.first(8).join
вы также можете использовать его для случайных паролей длиной 8
random_password = ('0'..'z').to_a.shuffle.first(8).join
Я надеюсь, что это поможет и удивительные.
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"
вот один простой код для случайного пароля с lenth 8
rand_password=('0'..'z').to_a.shuffle.first(8).join
надеюсь, это поможет.
имейте в виду:rand
предсказуемо для атакующего и поэтому, вероятно, небезопасно. Вы обязательно должны использовать SecureRandom, если это для генерации паролей. Я использую что-то вроде этого:
length = 10
characters = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a
password = SecureRandom.random_bytes(length).each_char.map do |char|
characters[(char.ord % characters.length)]
end.join
другой метод, который мне нравится использовать
rand(2**256).to_s(36)[0..7]
добавить ljust, если вы действительно параноик о правильной длине строки:
rand(2**256).to_s(36).ljust(8,'a')[0..7]
Я думаю, что это хороший баланс краткости, ясности и простоты модификации.
characters = ('a'..'z').to_a + ('A'..'Z').to_a
# Prior to 1.9, use .choice, not .sample
(0..8).map{characters.sample}.join
легко изменен
например, включая цифры:
characters = ('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a
верхний регистр шестнадцатеричное:
characters = ('A'..'F').to_a + (0..9).to_a
для действительно впечатляющего массива символов:
characters = (32..126).to_a.pack('U*').chars.to_a
можно использовать String#random
от граней Ruby Gem facets
:
он в основном делает это:
class String
def self.random(len=32, character_set = ["A".."Z", "a".."z", "0".."9"])
characters = character_set.map { |i| i.to_a }.flatten
characters_len = characters.length
(0...len).map{ characters[rand(characters_len)] }.join
end
end
это решение нуждается во внешней зависимости, но кажется красивее, чем другое.
- установить gem Факер
Faker::Lorem.characters(10) # => "ang9cbhoa8"
дано:
chars = [*('a'..'z'),*('0'..'9')].flatten
одно выражение, может быть передано в качестве аргумента, позволяет дублировать символы:
Array.new(len) { chars.sample }.join
мои 2 цента:
def token(length=16)
chars = [*('A'..'Z'), *('a'..'z'), *(0..9)]
(0..length).map {chars.sample}.join
end
Я просто пишу маленький камень random_token
чтобы генерировать случайные токены для большинства случаев использования, наслаждайтесь ~
С помощью этого метода можно передать в abitrary длина. Он установлен по умолчанию в 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
недавно я делал что-то подобное, чтобы сгенерировать 8-байтовую случайную строку из 62 символов. Символы были 0-9, a-z,A-Z. У меня был массив из них, который зацикливался 8 раз и выбирал случайное значение из массива. Это было внутри приложения rails.
str = ''
8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }
странно то, что у меня есть большое количество дубликатов. Теперь случайно это должно почти никогда не произойти. 62^8 огромен, но из 1200 или около того кодов в БД у меня было хорошее количество дубликаты. Я заметил, что они происходят на часовых границах друг друга. Другими словами, я могу увидеть дубль в 12: 12: 23 и 2:12: 22 или что-то в этом роде...не уверен, является ли время проблемой или нет.
этот код был в до создания объекта activerecord. Перед созданием записи этот код будет выполняться и генерировать "уникальный" код. Записи в БД всегда производились надежно, но код (str в приведенной выше строке) тоже дублировался часто.
Я создал скрипт для выполнения 100000 итераций этой строки с небольшой задержкой, поэтому потребуется 3-4 часа, надеясь увидеть какой-то шаблон повтора на почасовой основе, но ничего не увидел. Я понятия не имею, почему это происходило в моем приложении rails.