number - Cómo generar una cadena aleatoria en Ruby
random number ruby (30)
Actualmente estoy generando una cadena mayúscula pseudoaleatoria de 8 caracteres para "A" .. "Z":
value = ""; 8.times{value << (65 + rand(25)).chr}
pero no se ve limpio, y no se puede pasar como un argumento ya que no es una sola declaración. Para obtener una cadena de mayúsculas y minúsculas "a" .. "z" más "A" .. "Z", la cambié a:
value = ""; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}
pero parece basura
¿Alguien tiene un método mejor?
¿Por qué no usar SecureRandom?
require ''securerandom''
random_string = SecureRandom.hex
# outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81 (i.e. 32 chars of 0..9, a..f)
SecureRandom también tiene métodos para:
- base64
- random_bytes
- número aleatorio
consulte: http://ruby-doc.org/stdlib-1.9.2/libdoc/securerandom/rdoc/SecureRandom.html
Aquí hay un código simple para contraseña aleatoria con lenth 8
rand_password=(''0''..''z'').to_a.shuffle.first(8).join
Espero que ayude.
Aquí hay una línea de código simple para cadena aleatoria con longitud 8
random_string = (''0''..''z'').to_a.shuffle.first(8).join
También puedes usarlo para contraseña aleatoria de longitud 8.
random_password = (''0''..''z'').to_a.shuffle.first(8).join
Espero que te ayude y sea increíble.
Con este método se puede pasar en una longitud máxima. Se establece por defecto como 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
Creo que este es un buen balance de concisión, claridad y facilidad de modificación.
characters = (''a''..''z'').to_a + (''A''..''Z'').to_a
# Prior to 1.9, use .choice, not .sample
(0..8).map{characters.sample}.join
Fácilmente modificado
Por ejemplo, incluyendo dígitos:
characters = (''a''..''z'').to_a + (''A''..''Z'').to_a + (0..9).to_a
Hexadecimal mayúscula
characters = (''A''..''F'').to_a + (0..9).to_a
Para una impresionante variedad de personajes:
characters = (32..126).to_a.pack(''U*'').chars.to_a
Dado:
chars = [*(''a''..''z''),*(''0''..''9'')].flatten
Una sola expresión, se puede pasar como un argumento, permite caracteres duplicados:
Array.new(len) { chars.sample }.join
Desde ruby 2.5 realmente fácil con SecureRandom.alphanumeric
:
len = 8
SecureRandom.alphanumeric(len)
=> "larHSsgL"
Genera cadenas aleatorias que contienen AZ, az y 0-9 y, por lo tanto, deben ser aplicables en la mayoría de los casos de uso. Y se generan de forma aleatoria segura, lo que también podría ser un beneficio.
Edición: un punto de referencia para compararlo con la solución que tenga más votos:
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)
Así que la solución de rand
solo toma aproximadamente 3/4 del tiempo de SecureRandom
. Podría importar si realmente generas un montón de cadenas, pero si solo creas una cadena aleatoria de vez en cuando, siempre preferiría una implementación más segura (ya que también es más fácil de llamar y más explícita).
Esta solución genera una cadena de caracteres de fácil lectura para los códigos de activación; No quería que la gente confundiera 8 con B, 1 con I, 0 con O, L con 1, etc.
# 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
Esta solución necesita dependencia externa, pero parece más bonita que otra.
- Instalar gem faker
-
Faker::Lorem.characters(10) # => "ang9cbhoa8"
Estaba haciendo algo como esto recientemente para generar una cadena aleatoria de 8 bytes a partir de 62 caracteres. Los personajes fueron 0-9, az, AZ. Tuve una matriz de ellos ya que estaba haciendo un bucle 8 veces y seleccionando un valor aleatorio de la matriz. Esto estaba dentro de una aplicación de rieles.
str = '''' 8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }
Lo raro es que tengo un buen número de duplicados. Ahora al azar esto casi nunca debería suceder. 62 ^ 8 es enorme, pero de los aproximadamente 1200 códigos en la base de datos i tenía un buen número de duplicados. Me di cuenta de que sucedían en los límites de una hora del otro. En otras palabras, podría ver un duple a las 12:12:23 y 2:12:22 o algo así ... no estoy seguro de si el tiempo es el problema o no.
Este código estaba en la creación anterior de un objeto activerecord. Antes de crear el registro, este código se ejecutaría y generaría el código ''único''. Las entradas en la base de datos siempre se producían de forma confiable, pero el código (str en la línea anterior) se duplicaba con demasiada frecuencia.
Creé una secuencia de comandos para ejecutar 100000 iteraciones de esta línea anterior con un pequeño retraso, por lo que tomaría 3-4 horas esperando ver algún tipo de patrón de repetición cada hora, pero no vi nada. No tengo idea de por qué esto estaba sucediendo en mi aplicación de rieles.
Lo uso para generar cadenas aleatorias amigables con URL con una longitud máxima garantizada:
rand(36**length).to_s(36)
Genera cadenas aleatorias de az minúscula y 0-9. No es muy personalizable pero es corto y limpio.
Me gusta más la respuesta de Radar, hasta ahora, creo. Me pellizco un poco así:
CHARS = (''a''..''z'').to_a + (''A''..''Z'').to_a
def rand_string(length=8)
s=''''
length.times{ s << CHARS[rand(CHARS.length)] }
s
end
Mi favorito es (:A..:Z).to_a.shuffle[0,8].join
. Tenga en cuenta que la reproducción aleatoria requiere Ruby> 1.9.
Mis 2 centavos:
def token(length=16)
chars = [*(''A''..''Z''), *(''a''..''z''), *(0..9)]
(0..length).map {chars.sample}.join
end
No recuerdo dónde encontré esto, pero me parece que es el mejor y el menos intensivo de procesos:
def random_string(length=10)
chars = ''abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789''
password = ''''
length.times { password << chars[rand(chars.size)] }
password
end
Otro método que me gusta usar
rand(2**256).to_s(36)[0..7]
Agregue ljust si está realmente paranoico sobre la longitud correcta de la cadena:
rand(2**256).to_s(36).ljust(8,''a'')[0..7]
Otros han mencionado algo similar, pero esto utiliza la función segura de URL.
require ''securerandom''
p SecureRandom.urlsafe_base64(5) #=> "UtM7aa8"
p SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
p SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="
El resultado puede contener AZ, az, 0-9, “-” y “_”. "=" También se usa si el relleno es verdadero.
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"
Si quieres una cadena de longitud especificada, usa:
require ''securerandom''
randomstring = SecureRandom.hex(n)
Generará una cadena aleatoria de longitud 2n
contiene 0-9
y af
Simplemente agregando mis centavos aquí ...
def random_string(length = 8)
rand(32**length).to_s(32)
end
Solo escribo una pequeña gema random_token
para generar tokens aleatorios para la mayoría de los casos de uso, disfruta ~
Tenga en cuenta: rand
es predecible para un atacante y, por lo tanto, probablemente inseguro. Definitivamente deberías usar SecureRandom si esto es para generar contraseñas. Yo uso algo como esto:
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
puede usar String#random
de las facetas de las facetas de Ruby Gem:
básicamente hace esto:
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
Array.new(n){[*"0".."9"].sample}.join
, donde n = 8 en su caso.
Generalizado: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join
, etc. - de this respuesta
''''.tap {|v| 4.times { v << (''a''..''z'').to_a.sample} }
(0...8).map { (65 + rand(26)).chr }.join
Paso mucho tiempo jugando al golf.
(0...50).map { (''a''..''z'').to_a[rand(26)] }.join
Y una última que es aún más confusa, pero más flexible y desperdicia menos ciclos:
o = [(''a''..''z''), (''A''..''Z'')].map(&:to_a).flatten
string = (0...50).map { o[rand(o.length)] }.join
SecureRandom.base64(15).tr(''+/=lIO0'', ''pqrsxyz'')
Algo de Devise
[*(''A''..''Z'')].sample(8).join
Generar una cadena de 8 letras al azar (por ejemplo, NVAYXHGR)
([*(''A''..''Z''),*(''0''..''9'')]-%w(0 1 I O)).sample(8).join
Generar una cadena de 8 caracteres aleatorios (por ejemplo, 3PH4SWF2), excluye 0/1 / I / O. Ruby 1.9
require ''securerandom''
SecureRandom.urlsafe_base64(9)
require ''sha1''
srand
seed = "--#{rand(10000)}--#{Time.now}--"
Digest::SHA1.hexdigest(seed)[0,8]