Domanda

Attualmente sto generando una stringa maiuscola pseudo-casuale di 8 caratteri per "A" .."Z":

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

ma non sembra pulito e non può essere passato come argomento poiché non è una singola istruzione.Per ottenere una stringa "a" composta da maiuscole e minuscole .."z" più "A"..."Z", l'ho cambiato in:

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

ma sembra spazzatura.

Qualcuno ha un metodo migliore?

È stato utile?

Soluzione

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

Trascorro troppo tempo giocando a golf.

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

E un'ultima ancora più confusa, ma più flessibile e che spreca meno cicli:

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

Altri suggerimenti

Perché non utilizzare SecureRandom?

require 'securerandom'
random_string = SecureRandom.hex

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

SecureRandom dispone anche di metodi per:

  • base64
  • byte_casuali
  • numero casuale

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

Lo uso per generare stringhe URL friendly casuali con una lunghezza massima garantita:

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

Genera stringhe casuali di lettere minuscole a-z e 0-9.Non è molto personalizzabile ma è breve e pulito.

Questa soluzione genera una stringa di caratteri facilmente leggibili per i codici di attivazione;Non volevo che la gente confondesse 8 con B, 1 con I, 0 con O, L con 1, ecc.

# 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

Altri hanno menzionato qualcosa di simile, ma questo utilizza la funzione URL sicura.

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

Il risultato può contenere A-Z, a-z, 0-9, “-” e “_”.“=" viene utilizzato anche se il riempimento è vero.

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

Genera una stringa casuale di 8 lettere (es.NVAYXHGR)

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

Genera una stringa casuale di 8 caratteri (es.3PH4SWF2), esclude 0/1/I/O.Rubino 1.9

Dal momento che Ruby 2.5 è davvero facile SecureRandom.alphanumeric:

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

Genera stringhe casuali contenenti A-Z, a-z e 0-9 e pertanto dovrebbe essere applicabile nella maggior parte dei casi d'uso.E vengono generati in modo casuale e sicuro, il che potrebbe essere anche un vantaggio.


Modificare:Un benchmark per confrontarlo con la soluzione con più voti positivi:

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)

Così il rand la soluzione richiede solo circa 3/4 del tempo SecureRandom.Potrebbe avere importanza se generi davvero molte stringhe, ma se crei solo qualche stringa casuale di tanto in tanto, opterei sempre per l'implementazione più sicura (poiché è anche più facile da chiamare e più esplicita).

Non riesco a ricordare dove l'ho trovato, ma mi sembra il migliore e il meno impegnativo in termini di processo:

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

Se vuoi una stringa della lunghezza specificata, usa:

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

Genererà una stringa casuale di lunghezza 2n contenente 0-9 E a-f

Array.new(n){[*"0".."9"].sample}.join, dove n = 8 nel tuo caso.

Generalizzato: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join, eccetera.- da Questo risposta

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

Ecco un semplice codice di una riga per una stringa casuale con lunghezza 8

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

Puoi anche usarlo per password casuali di lunghezza 8

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

spero che possa essere d'aiuto e fantastico.

Rubino 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"

Ecco un semplice codice per una password casuale con lunghezza 8

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

Spero che possa essere d'aiuto.

Essere consapevoli: rand è prevedibile per un utente malintenzionato e quindi probabilmente insicuro.Dovresti assolutamente usare SecureRandom se serve per generare password.Io uso qualcosa del genere:

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

Un altro metodo che mi piace usare

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

Aggiungi ljust se sei davvero paranoico riguardo alla lunghezza corretta della stringa:

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

Qualcosa da Devise

Penso che questo sia un buon equilibrio tra concisione, chiarezza e facilità di modifica.

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

Facilmente modificabile

Ad esempio, includendo le cifre:

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

Esadecimale maiuscolo:

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

Per una gamma di personaggi davvero impressionante:

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

Aggiungo solo i miei centesimi qui...

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

Puoi usare String#random dalle sfaccettature della gemma rubino facets:

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

sostanzialmente fa questo:

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

Il mio preferito è (:A..:Z).to_a.shuffle[0,8].join.Tieni presente che la riproduzione casuale richiede Ruby > 1.9.

Questa soluzione necessita di dipendenza esterna, ma sembra più carina di un'altra.

  1. Installa la gemma falso
  2. Faker::Lorem.characters(10) # => "ang9cbhoa8"

Dato:

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

L'espressione singola, che può essere passata come argomento, consente caratteri duplicati:

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

Recentemente stavo facendo qualcosa del genere per generare una stringa casuale di 8 byte da 62 caratteri.I caratteri erano 0-9,a-z,A-Z.Ne avevo un array mentre eseguivo il loop 8 volte e sceglievo un valore casuale dall'array.Questo era all'interno di un'app ferroviaria.

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

La cosa strana è che ho ottenuto un buon numero di duplicati.Ora, casualmente, questo non dovrebbe praticamente mai accadere.62 ^ 8 è enorme, ma su circa 1200 codici nel db ho avuto un buon numero di duplicati.Ho notato che accadevano a intervalli di ore l'uno dall'altro.In altre parole, potrei vedere un doppio alle 12:12:23 e alle 2:12:22 o qualcosa del genere... non sono sicuro se il problema sia il tempo o meno.

Questo codice era presente prima della creazione di un oggetto activerecord.Prima che il record fosse creato, questo codice veniva eseguito e generava il codice "univoco".Le voci nel db venivano sempre prodotte in modo affidabile, ma il codice (str nella riga sopra) veniva duplicato troppo spesso.

Ho creato uno script per eseguire 100.000 iterazioni di questa riga sopra con un piccolo ritardo, quindi ci vorrebbero 3-4 ore sperando di vedere una sorta di schema di ripetizione su base oraria, ma non ho visto nulla.Non ho idea del motivo per cui ciò accadesse nella mia app Rails.

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

I miei 2 centesimi:

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

Scrivo solo un piccolo gioiello random_token per generare token casuali per la maggior parte dei casi d'uso, divertiti con ~

https://github.com/sibevin/random_token

Con questo metodo puoi passare in una lunghezza arbitraria.È impostato come predefinito su 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

Penso che finora mi piaccia di più la risposta di Radar.Io modificherei un po' così:

CHARS = ('a'..'z').to_a + ('A'..'Z').to_a
def rand_string(length=8)
  s=''
  length.times{ s << CHARS[rand(CHARS.length)] }
  s
end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top