Wie eine zufällige Zeichenfolge in Ruby erzeugen
Frage
Ich bin derzeit Erzeugung eines 8-stelligen Pseudozufallsgroß Zeichenfolge für "A" .. "Z":
value = ""; 8.times{value << (65 + rand(25)).chr}
, aber es sieht nicht sauber, und es kann nicht als Argument übergeben werden, da es keine einzige Aussage. Um eine mixed-case Zeichenfolge "a" .. "z" plus "A" .. "Z" zu bekommen, habe ich es zu:
value = ""; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}
, aber es sieht aus wie Müll.
Hat jemand eine bessere Methode hat?
Lösung
(0...8).map { (65 + rand(26)).chr }.join
Ich verbringe zu viel Zeit Golfen.
(0...50).map { ('a'..'z').to_a[rand(26)] }.join
Und ein letzter, die noch verwirrender ist, aber flexibler und Abfälle weniger Zyklen:
o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
string = (0...50).map { o[rand(o.length)] }.join
Andere Tipps
Warum nicht Secure benutzen?
require 'securerandom'
random_string = SecureRandom.hex
# outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81 (i.e. 32 chars of 0..9, a..f)
Secure hat auch Methoden für:
- base64
- random_bytes
- random_number
siehe: http: // ruby-doc. org / stdlib-1.9.2 / libdoc / Secure / rdoc / SecureRandom.html
Ich benutze diese zur Erzeugung von Zufalls URL freundliche Strings mit einer garantierten maximalen Länge:
rand(36**length).to_s(36)
Es erzeugt zufällige Zeichenkette von Klein a-z und 0-9. Es ist nicht sehr individuell, aber es ist kurz und sauber.
Diese Lösung erzeugt eine Reihe von leicht lesbaren Zeichen für Aktivierungscodes; Ich wollte nicht, Menschen verwirrend 8 mit B, 1 mit I, 0 mit O, L mit 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
Andere haben etwas ähnliches erwähnt, aber diese verwendet die URL sichere Funktion.
require 'securerandom'
p SecureRandom.urlsafe_base64(5) #=> "UtM7aa8"
p SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
p SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="
Das Ergebnis kann enthält ein-Z, a-z, 0-9, „-“ und „_“. „=“ Wird auch verwendet, wenn padding wahr ist.
[*('A'..'Z')].sample(8).join
Generieren eines Zufalls 8 Buchstabenfolge (z NVAYXHGR)
([*('A'..'Z'),*('0'..'9')]-%w(0 1 I O)).sample(8).join
Generieren eines Zufalls 8 Zeichenkette (beispiels 3PH4SWF2) schließt 0/1 / I / O. Ruby 1.9
Da Rubin 2.5 einfach mit SecureRandom.alphanumeric
:
len = 8
SecureRandom.alphanumeric(len)
=> "larHSsgL"
Erzeugt zufällige Zeichenkette A-Z enthalten, a-z und 0-9 und daher anwendbar sein sollten in den meisten Anwendungsfällen. Und sie werden zufällig sicher erzeugt, was ein Vorteil sein könnte, auch.
Edit: Ein Benchmark es mit der Lösung zu vergleichen, die die meisten upvotes mit:
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)
So ist die rand
Lösung dauert nur etwa 3/4 der Zeit von SecureRandom
. Rolle könnte, wenn Sie wirklich eine Menge Saiten erzeugen, aber wenn Sie nur eine zufällige Zeichenfolge von Zeit zu Zeit erstellen würde ich immer mit der sichereren Implementierung gehen (da es auch leichter zu nennen und expliziter ist).
Ich kann mich nicht erinnern, wo ich das gefunden, aber es scheint, wie das am besten und den am wenigsten Prozess intensiv zu mir:
def random_string(length=10)
chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
password = ''
length.times { password << chars[rand(chars.size)] }
password
end
require 'securerandom'
SecureRandom.urlsafe_base64(9)
Wenn Sie einen String der angegebenen Länge möchten, verwenden Sie:
require 'securerandom'
randomstring = SecureRandom.hex(n)
Es wird eine zufällige Zeichenfolge der Länge 2n
enthält 0-9
und a-f
Array.new(n){[*"0".."9"].sample}.join
,
wobei n = 8 in Ihrem Fall.
Generalized: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join
etc. - von diese beantworten
require 'sha1'
srand
seed = "--#{rand(10000)}--#{Time.now}--"
Digest::SHA1.hexdigest(seed)[0,8]
Hier ist eine Zeile einfacher Code für zufälligen Zeichenfolge mit einer Länge von 8
random_string = ('0'..'z').to_a.shuffle.first(8).join
Sie können es auch für zufällige Passwörter verwenden, die Länge 8
random_password = ('0'..'z').to_a.shuffle.first(8).join
ich hoffe, es wird helfen, und erstaunlich.
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"
Hier ist ein einfacher Code für zufällige Passwörter mit einer Länge von 8
rand_password=('0'..'z').to_a.shuffle.first(8).join
Hoffe, es wird helfen.
Bitte beachten Sie: rand
für einen Angreifer vorhersehbar ist und daher wahrscheinlich unsicher. Sie sollten auf jeden Fall Secure verwenden, wenn dies zur Erzeugung von Passwörtern ist. Ich benutze so etwas wie folgt aus:
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
Eine andere Methode Ich mag verwenden
rand(2**256).to_s(36)[0..7]
In ljust wenn Sie wirklich paranoid über die korrekte Stringlänge sind:
rand(2**256).to_s(36).ljust(8,'a')[0..7]
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
Etwas von Devise
Ich denke, das ist eine gute Balance von Prägnanz, Klarheit und Einfachheit der Änderung.
characters = ('a'..'z').to_a + ('A'..'Z').to_a
# Prior to 1.9, use .choice, not .sample
(0..8).map{characters.sample}.join
leicht modifiziert
Zum Beispiel, einschließlich der Ziffern:
characters = ('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a
Versalien- hexadezimal:
characters = ('A'..'F').to_a + (0..9).to_a
Für eine wirklich beeindruckende Reihe von Zeichen:
characters = (32..126).to_a.pack('U*').chars.to_a
Nur das Hinzufügen meines Cent hier ...
def random_string(length = 8)
rand(32**length).to_s(32)
end
Sie können String#random
von den Facetten von Ruby Gem facets
verwenden:
es im Grunde tut dies:
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
Mein Favorit ist (:A..:Z).to_a.shuffle[0,8].join
. Beachten Sie, dass shuffle setzt Rubin> 1.9.
Diese Lösung benötigt externe Abhängigkeit, scheint aber schöner als andere.
- Installieren gem faker
-
Faker::Lorem.characters(10) # => "ang9cbhoa8"
Gegeben:
chars = [*('a'..'z'),*('0'..'9')].flatten
Single Ausdruck kann als Argument übergeben wird, läßt doppelte Zeichen:
Array.new(len) { chars.sample }.join
Ich war so etwas wie dies zu tun vor kurzem eine 8-Byte-zufällige Zeichenfolge aus 62 Zeichen zu erzeugen. Die Zeichen waren 0-9, a-z, A-Z. Ich hatte von ihnen wurde ein Array als 8mal Looping und einen Zufallswert aus dem Array Kommissionierung. Dies war in einer Rails-Anwendung.
str = ''
8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }
Die seltsame Sache ist, dass ich eine gute Anzahl von Duplikaten bekam. Jetzt zufällig sollte dies so ziemlich nie passieren. 62 ^ 8 ist riesig, aber aus 1200 oder so Codes in der db hatte ich eine gute Anzahl von Duplikaten. Ich bemerkte sie auf Stunde Grenzen voneinander geschieht. Mit anderen Worten, ich könnte einen Zweier bei 12.12.23 und 02.12.22 oder so ähnlich sieht ... nicht sicher, ob die Zeit das Problem ist oder nicht.
Dieser Code wurde in dem vor einem Activerecord-Objekt erstellen. Vor der Aufzeichnung dieser Code erstellt wurde, würde die ‚einmalige‘ Code auszuführen und generieren. Einträge in den db wurden immer zuverlässig hergestellt, aber der Code (str in der oberen Zeile) wurde viel zu oft dupliziert werden.
habe ich ein Skript über 100.000 Iterationen dieser über die Linie mit kleiner Verzögerung laufen, so dass es 3-4 Stunden eine Art Wiederholungsmuster auf stündliche Basis der Hoffnung nehmen würde, um zu sehen, sah aber nichts. Ich habe keine Ahnung, warum dies in meiner Rails-Anwendung geschieht.
''.tap {|v| 4.times { v << ('a'..'z').to_a.sample} }
Meine 2 Cent:
def token(length=16)
chars = [*('A'..'Z'), *('a'..'z'), *(0..9)]
(0..length).map {chars.sample}.join
end
Ich schreibe gerade ein kleines Juwel random_token
zufällige Token für die meisten Anwendungsfälle zu erzeugen, genießen ~
Mit dieser Methode können Sie in beliebiger Länge passieren. Es ist festgelegt als Standard als 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
Ich mag Radar Antwort am besten, so weit, denke ich. Ich würde zwicken ein wenig wie folgt aus:
CHARS = ('a'..'z').to_a + ('A'..'Z').to_a
def rand_string(length=8)
s=''
length.times{ s << CHARS[rand(CHARS.length)] }
s
end