Pregunta

Actualmente estoy generando un carácter de 8 pseudo-aleatorio en mayúsculas de la cadena para la "A" .."Z":

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

pero no se ve limpio, y no puede ser pasado como argumento, ya que no es una sola instrucción.Para obtener un caso mixto de cadena "a" .."z" plus "A" .."Z", he cambiado a:

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

pero parece que a la basura.

¿Alguien tiene un método mejor?

¿Fue útil?

Solución

(0...8).map { (65 + rand(26)).chr }.join

Puedo dedicar demasiado tiempo a jugar al golf.

(0...50).map { ('a'..'z').to_a[rand(26)] }.join

Y una última, que es aún más confuso, pero más flexible y gasta menos ciclos:

o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
string = (0...50).map { o[rand(o.length)] }.join

Otros consejos

¿Por qué no utilizar 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
  • random_number

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

Yo uso esto para la generación aleatoria de URL amigable cadenas con un garantizado longitud máxima:

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

Se genera al azar cadenas de caracteres a-z y 0-9.No es muy personalizable, pero es corto y limpio.

Esta solución genera una cadena de caracteres fácilmente legibles para los códigos de activación;No quería que la gente confunde con 8 B, 1 con I, 0 con S, 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

Otros han mencionado algo similar, pero este usa la URL de la caja fuerte de la función.

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 a-Z, a-z, 0-9, "-" y "_"."=" se utiliza también si el relleno es cierto.

[*('A'..'Z')].sample(8).join

Generar al azar 8 de la carta de la cadena (por ejemplo,NVAYXHGR)

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

Generar al azar 8 cadena de caracteres (por ejemplo,3PH4SWF2), excluye 0/1/I/O.Ruby 1.9

Desde ruby 2.5 realmente fácil con SecureRandom.alphanumeric:

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

Genera al azar cadenas que contiene a-Z, a-z y 0-9 y por lo tanto debe ser aplicable en la mayoría de los casos de uso.Y que se genera de forma aleatoria segura, lo que podría ser un beneficio, también.


Editar:Un punto de referencia para comparar con la solución de tener la mayoría de 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)

Por lo que el rand la solución, sólo toma alrededor de 3/4 de tiempo de SecureRandom.Podría importa si usted generar realmente una gran cantidad de cadenas de caracteres, pero si usted acaba de crear algunos cadena aleatoria de vez en cuando me gustaría ir siempre con la más segura de la aplicación (ya que también es más fácil llamar y más explícito).

No recuerdo donde he encontrado esto, pero parece que la mejor y la menos proceso intensivo para mí:

def random_string(length=10)
  chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
  password = ''
  length.times { password << chars[rand(chars.size)] }
  password
end
require 'securerandom'
SecureRandom.urlsafe_base64(9)

Si desea una cadena de longitud especificada, utilice:

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

Se genera una cadena aleatoria de longitud 2n contiene 0-9 y a-f

Array.new(n){[*"0".."9"].sample}.join, donde n=8 en su caso.

Generalizada: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join, etc.- de este respuesta

require 'sha1'
srand
seed = "--#{rand(10000)}--#{Time.now}--"
Digest::SHA1.hexdigest(seed)[0,8]

Aquí está una línea de código sencillo para cadena aleatoria con una longitud de 8

 random_string = ('0'..'z').to_a.shuffle.first(8).join

También se puede utilizar para la contraseña aleatoria que tienen una longitud de 8

random_password = ('0'..'z').to_a.shuffle.first(8).join

espero que ayude y sorprendente.

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"

Aquí es un simple código de contraseña aleatoria con lenth 8

rand_password=('0'..'z').to_a.shuffle.first(8).join

Espero que le ayude.

Tenga en cuenta que: rand es previsible que un atacante y por lo tanto probablemente inseguro.Definitivamente, usted debe utilizar SecureRandom si esto es para la generación de 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

Otro método me gusta usar

 rand(2**256).to_s(36)[0..7]

Agregar ljust si eres muy paranoico acerca de la correcta longitud de la cadena:

 rand(2**256).to_s(36).ljust(8,'a')[0..7]
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')

Algo de Idear

Creo que este es un buen equilibrio de la concisión, la claridad y la 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ácil de modificar

Por ejemplo, incluidos los dígitos:

characters = ('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a

Mayúsculas hexadecimal:

characters = ('A'..'F').to_a + (0..9).to_a

Para un verdaderamente impresionante variedad de personajes:

characters = (32..126).to_a.pack('U*').chars.to_a

Sólo añadir mi centavos aquí...

def random_string(length = 8)
  rand(32**length).to_s(32)
end

puede utilizar String#random a partir de las Facetas de la Gema de Ruby facets:

https://github.com/rubyworks/facets/blob/126a619fd766bc45588cac18d09c4f1927538e33/lib/core/facets/string/random.rb

que 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

Mi favorito es (:A..:Z).to_a.shuffle[0,8].join.Tenga en cuenta que shuffle requiere Ruby > 1.9.

Esta solución de necesidades de la dependencia externa, pero parece más bonita que la otra.

  1. Instalar la gema faker
  2. Faker::Lorem.characters(10) # => "ang9cbhoa8"

Dado:

chars = [*('a'..'z'),*('0'..'9')].flatten

Sola expresión, puede ser pasado como argumento, permite a los caracteres duplicados:

Array.new(len) { chars.sample }.join

Yo estaba haciendo algo como esto recientemente para generar un byte de 8 cadena aleatoria de 62 caracteres.Los caracteres 0-9,a-z,A-Z.Yo tenía una colección de ellos, como fue el bucle de 8 veces y escoger un valor aleatorio de la matriz.Este estaba dentro de una aplicación rails.

str = '' 8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }

Lo extraño es que tengo buen número de duplicados.Ahora al azar esta debe bastante mucho nunca sucederá.62^8 es enorme, pero fuera de 1200 o así los códigos en el db he tenido un buen número de duplicados.Me di cuenta de que se están realizando en la hora de los límites de cada uno de los otros.En otras palabras, se podría ver un duple a las 12:12:23 y 2:12:22 o algo así...no estoy seguro si el tiempo es el problema o no.

Este código fue en el antes de crear un objeto activerecord.Antes de que se creó el registro de este código se ejecuta y generar la "única" del código.Las entradas en la base de datos se produce siempre de forma fiable, pero el código (str en la línea anterior), se duplican demasiado a menudo.

He creado un script para que se ejecute a través de 100000 iteraciones de este por encima de la línea con el pequeño retraso, por lo que podría tomar de 3-4 horas con la esperanza de ver algún tipo de repetición del patrón en una hora, pero no vi nada.No tengo idea de por qué estaba pasando esto en mi aplicación rails.

''.tap {|v| 4.times { v << ('a'..'z').to_a.sample} }

Mis 2 centavos:

  def token(length=16)
    chars = [*('A'..'Z'), *('a'..'z'), *(0..9)]
    (0..length).map {chars.sample}.join
  end

Acabo de escribir una pequeña joya random_token para generar al azar fichas para la mayoría de los casos de uso, disfruten ~

https://github.com/sibevin/random_token

Con este método se puede pasar en un abitrary de longitud.Se establece como predeterminado 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

Me gusta Radar respuesta mejor, hasta ahora, creo.Me gustaría retocar un poco como esto:

CHARS = ('a'..'z').to_a + ('A'..'Z').to_a
def rand_string(length=8)
  s=''
  length.times{ s << CHARS[rand(CHARS.length)] }
  s
end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top