Pergunta

Atualmente estou gerando uma cadeia de caracteres em maiúsculas pseudo-aleatório de 8 caracteres para "A" .. "Z":

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

mas não parece limpo, e não pode ser passado como um argumento, uma vez que não é uma única instrução. Para obter uma seqüência de letras maiúsculas e minúsculas "a" .. "z" plus "A" .. "Z", o texto foi alterado para:

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

mas parece que lixo.

Alguém tem um método melhor?

Foi útil?

Solução

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

I gastar muito golfe tempo.

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

E a última que é ainda mais confuso, mas mais flexíveis e desperdiça menos ciclos:

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

Outras dicas

Por que não usar SecureRandom?

require 'securerandom'
random_string = SecureRandom.hex

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

SecureRandom também tem métodos para:

  • base64
  • random_bytes
  • random_number

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

Eu uso isso para a geração de cordas amigáveis ??URL aleatória com um comprimento máximo garantido:

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

Ele gera cadeias aleatórias de um-z minúsculas e 0-9. Não é muito personalizável, mas é curto e limpo.

Esta solução gera uma cadeia de caracteres facilmente legíveis para códigos de ativação; Eu não queria que as pessoas confusas 8 com B, 1 com I, 0 com O, L com 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

Outros mencionaram algo semelhante, mas este usa a função segura URL.

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

O resultado pode conter A-Z, um-z, 0-9, “-” e “_”. “=” Também é usado se o preenchimento é verdade.

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

Gerar um aleatória 8 carta string (por exemplo NVAYXHGR)

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

Gerar um aleatória 8 cadeia de caracteres (por exemplo 3PH4SWF2), exclui 0/1 / I / O. Ruby 1.9

Desde rubi 2,5 realmente fácil com SecureRandom.alphanumeric:

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

Gera cadeias aleatórias que contenham A-Z, um-z e 0-9 e, por conseguinte, deve ser aplicável na maioria dos casos de utilização. E eles são gerados aleatoriamente seguro, que pode ser um benefício, também.


Edit: Uma referência para compará-lo com a solução de ter a maioria dos 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)

Portanto, a solução rand só leva cerca de 3/4 do tempo de SecureRandom. Pode importa se você gerar realmente um monte de cordas, mas se você apenas criar alguma seqüência aleatória de tempos em tempos eu sempre ir com a implementação mais segura (uma vez que também é mais fácil de chamar e mais explícita).

Não me lembro onde eu encontrei isso, mas parece que o melhor eo menos intenso processo para mim:

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

Se você quer uma cadeia de comprimento especificado, use:

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

Ele irá gerar uma seqüência aleatória de 2n comprimento contendo 0-9 e a-f

Array.new(n){[*"0".."9"].sample}.join, onde n = 8 no seu caso.

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

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

Aqui está um código simples uma linha para seqüência aleatória com comprimento de 8

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

Você também pode usá-lo para a senha aleatória com comprimento de 8

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

Espero que ele vai ajudar e surpreendente.

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"

Aqui está um código simples para senhas aleatórias com comprimento de 8

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

Hope ele vai ajudar.

Esteja ciente: rand é previsível para um atacante e, portanto, provavelmente inseguro. Você deve definitivamente usar SecureRandom se isto é para gerar senhas. Eu uso algo como isto:

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

Outro método que eu gosto de usar

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

Adicionar ljust se você for realmente paranóico sobre o comprimento da corda correto:

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

Algo de Devise

Eu acho que este é um bom equilíbrio de concisão, clareza e facilidade de modificação.

characters = ('a'..'z').to_a + ('A'..'Z').to_a
# Prior to 1.9, use .choice, not .sample
(0..8).map{characters.sample}.join

facilmente modificado

Por exemplo, incluindo dígitos:

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

Maiúsculas hexadecimal:

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

Para uma matriz verdadeiramente impressionante de personagens:

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

Basta adicionar meus centavos aqui ...

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

Você pode usar String#random das facetas do Ruby Gem facets:

https://github.com/ RubyWorks / facetas / blob / 126a619fd766bc45588cac18d09c4f1927538e33 / lib / core / facetas / string / random.rb

que basicamente faz isso:

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

O meu favorito é (:A..:Z).to_a.shuffle[0,8].join. Note-se que shuffle requer Rubi> 1.9.

Esta solução precisa de dependência externa, mas parece mais bonita que a outra.

  1. Instale gem faker
  2. Faker::Lorem.characters(10) # => "ang9cbhoa8"

Dada:

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

expressão única, pode ser passado como um argumento, permite caracteres duplicados:

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

Eu estava fazendo algo parecido com isto recentemente para gerar uma seqüência aleatória de 8 bytes de 62 caracteres. Os caracteres foram 0-9, um-z, A-Z. Eu tive uma série de-los como foi looping 8 vezes e escolher um valor aleatório para fora da matriz. Este estava dentro de uma app Rails.

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

O estranho é que eu tenho bom número de duplicatas. Agora aleatoriamente esta praticamente nunca deveria acontecer. 62 ^ 8 é enorme, mas fora de 1200 ou assim códigos no db i teve um bom número de duplicatas. Notei-los acontecendo em limites hora um do outro. Em outras palavras eu poderia ver um duple em 0:12:23 e 2:12:22, ou algo assim ... não tenho certeza se o tempo é a questão ou não.

Este código estava no antes de criar de um objeto activerecord. Antes do registro foi criado este código seria executado e gerar o código 'único'. Entradas no db foram sempre produzidos de forma confiável, mas o código (str na linha acima) estava sendo duplicado com muita freqüência.

Eu criei um script para ser executado através de 100000 iterações desta linha acima com pequeno atraso de modo que levaria 3-4 horas esperando para ver algum tipo de padrão de repetição numa base horária, mas não viu nada. Eu não tenho idéia por que isso estava acontecendo na minha rails aplicativo.

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

Meus 2 centavos:

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

Eu só escrever um pequeno random_token gem para gerar tokens aleatórios para mais casos de uso, desfrutar ~

https://github.com/sibevin/random_token

Com este método você pode passar em um comprimento arbitrário. É definido como um padrão 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

Eu gosto de resposta de Radar melhor, até agora, eu acho. Eu ajustar um pouco como este:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top