2868 Stimmen

Zufällige Zeichenketten/Zeichen in JavaScript generieren

Ich möchte eine 5-Zeichen-Zeichenfolge, die aus zufällig ausgewählten Zeichen aus der Menge [a-zA-Z0-9] .

Wie lässt sich dies am besten mit JavaScript bewerkstelligen?

91 Stimmen

Warnung: Keine der Antworten hat einen true-random Ergebnis! Sie sind nur pseudo-random . Wenn Sie zufällige Zeichenfolgen zum Schutz oder zur Sicherheit verwenden, verwenden Sie keine davon! Versuchen Sie eine dieser Api's: random.org

65 Stimmen

Math.random().toString(36).replace(/[^a-z]+/g, '')

24 Stimmen

Bitte legen Sie die Lösung in eine Lösung.

3728voto

csharptest.net Punkte 58070

Ich denke, das wird für Sie funktionieren:

function makeid(length) {
    var result           = '';
    var characters       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var charactersLength = characters.length;
    for ( var i = 0; i < length; i++ ) {
      result += characters.charAt(Math.floor(Math.random() * 
 charactersLength));
   }
   return result;
}

console.log(makeid(5));

127 Stimmen

@dan_waterworth Es spielt wahrscheinlich keine Rolle in fast jede Fall: codinghorror.com/blog/2009/01/

5 Stimmen

Es mag falsch aussehen, aber floor wird nicht benötigt: for(var text=''; text.length < 5;) text += possible.charAt(Math.random() * possible.length)

11 Stimmen

@dan_waterworth, Eigentlich, += ist aus irgendeinem Grund oft schneller, auch innerhalb von Schleifen - jsperf.com/beitreten-vs-verkettung

969voto

Mulan Punkte 117501

Math.random ist schlecht für diese Art von Dingen

Option 1

Wenn Sie in der Lage sind, dies zu tun Server -Seite, verwenden Sie einfach die Krypto Modul -

var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');

// "bb5dc8842ca31d4603d6aa11448d1654"

Die resultierende Zeichenkette ist doppelt so lang wie die zufällig erzeugten Bytes; jedes in Hexadezimal kodierte Byte besteht aus 2 Zeichen. 20 Bytes sind also 40 Zeichen in Hexadezimalzeichen.


Option 2

Wenn Sie dies tun müssen Kunde -Seite, vielleicht versuchen Sie das uuid-Modul -

var uuid = require("uuid");
var id = uuid.v4();

// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"

Option 3

Wenn Sie dies tun müssen Kunde -Seite und Sie müssen keine alten Browser unterstützen, Sie können es ohne Abhängigkeiten tun -

// dec2hex :: Integer -> String
// i.e. 0-255 -> '00'-'ff'
function dec2hex (dec) {
  return dec.toString(16).padStart(2, "0")
}

// generateId :: Integer -> String
function generateId (len) {
  var arr = new Uint8Array((len || 40) / 2)
  window.crypto.getRandomValues(arr)
  return Array.from(arr, dec2hex).join('')
}

console.log(generateId())
// "82defcf324571e70b0521d79cce2bf3fffccd69"

console.log(generateId(20))
// "c1a050a4cd1556948d41"

Für weitere Informationen über crypto.getRandomValues -

El crypto.getRandomValues() Methode können Sie kryptografisch starke Zufallswerte erhalten. Das als Parameter angegebene Array wird mit Zufallszahlen gefüllt (zufällig in seiner kryptographischen Bedeutung).

Hier ein kleines Konsolenbeispiel -

> var arr = new Uint8Array(4) # make array of 4 bytes (values 0-255)
> arr
Uint8Array(4) [ 0, 0, 0, 0 ]

> window.crypto
Crypto { subtle: SubtleCrypto }

> window.crypto.getRandomValues()
TypeError: Crypto.getRandomValues requires at least 1 argument, but only 0 were passed

> window.crypto.getRandomValues(arr)
Uint8Array(4) [ 235, 229, 94, 228 ]

Für IE11-Unterstützung können Sie -

(window.crypto || window.msCrypto).getRandomValues(arr)

Für Browserabdeckung siehe https://caniuse.com/#feat=getrandomvalues

0 Stimmen

Beachten Sie, dass bei UUIDs der Version 4 nicht alle Zeichen zufällig sind. Aus Wikipedia: "UUIDs der Version 4 haben die Form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, wobei x eine beliebige Hexadezimalziffer und y eine der Zahlen 8, 9, A oder B ist". ( de.wikipedia.org/wiki/ )

0 Stimmen

@wmassingham, ich bin mir nicht sicher, ob ich den Zweck Ihres Kommentars verstehe. Wollen Sie damit etwas über die Einzigartigkeit aufgrund einiger fester Zeichen in einer v4 uuid andeuten?

7 Stimmen

Ganz genau. Während eine UUID gut geeignet ist, um einer Sache eine ID zuzuweisen, ist die Verwendung als Zeichenkette aus zufälligen Zeichen aus diesem (und wahrscheinlich anderen) Gründen keine gute Idee.

334voto

Silver Ringvee Punkte 4102

Kurz, einfach und zuverlässig

Gibt genau 5 zufällige Zeichen zurück, im Gegensatz zu einigen der am besten bewerteten Antworten, die hier zu finden sind.

Math.random().toString(36).slice(2, 7);

26 Stimmen

Was wäre, wenn Math.random().toString(36) eine Zahl mit weniger als 5 Zeichen zurückgibt?

1 Stimmen

SilverRingvee hat wahrscheinlich nur kopiert der Kommentar von @dragon in der zweiten Antwort. Ehre, wem Ehre gebührt.

8 Stimmen

Nun, das ist eine interessante Anschuldigung von @Aperçu. Ich behaupte nicht, dass ich die Lösung erfunden habe, aber ich verwende sie schon seit Jahren in meinen Projekten. Und es hat nichts mit dem von Ihnen erwähnten Kommentar zu tun. Und ich bin mir ziemlich sicher, dass es in SO darauf ankommt, die nützlichsten Informationen an der richtigen Stelle zu finden, auch wenn sie bereits an anderer Stelle vorhanden sind. Glücklicherweise scheinen mindestens 51 Leute diese Antwort nützlich gefunden zu haben, gern geschehen!

193voto

amichair Punkte 3905

Hier ist eine Verbesserung gegenüber die ausgezeichnete Antwort von doubletap . Das Original hat zwei Nachteile, die hier angesprochen werden:

Wie bereits von anderen erwähnt, besteht eine geringe Wahrscheinlichkeit, dass kurze Zeichenketten oder sogar eine leere Zeichenkette (wenn die Zufallszahl 0 ist) erzeugt werden, was Ihre Anwendung stören könnte. Hier ist eine Lösung:

(Math.random().toString(36)+'00000000000000000').slice(2, N+2)

Zweitens begrenzen sowohl das Original als auch die obige Lösung die Zeichenfolgengröße N auf 16 Zeichen. Die folgende Lösung liefert eine Zeichenkette der Größe N für jedes beliebige N (beachten Sie jedoch, dass die Verwendung von N > 16 weder die Zufälligkeit erhöht noch die Wahrscheinlichkeit von Kollisionen verringert):

Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)

Erläuterung:

  1. Wählen Sie eine Zufallszahl im Bereich [0,1), d.h. zwischen 0 (einschließlich) und 1 (ausschließlich).
  2. Konvertieren Sie die Zahl in eine Zeichenkette zur Basis-36, d. h. mit den Zeichen 0-9 und a-z.
  3. Mit Nullen auffüllen (löst das erste Problem).
  4. Schneiden Sie das führende Präfix "0." und die zusätzlichen Nullen zum Auffüllen ab.
  5. Wiederholen Sie die Zeichenkette so oft, dass sie mindestens N Zeichen enthält (indem Sie leere Zeichenketten mit der kürzeren Zufallszeichenkette als Begrenzer verbinden).
  6. Schneidet genau N Zeichen aus der Zeichenkette aus.

Weitere Gedanken:

  • Bei dieser Lösung werden keine Großbuchstaben verwendet, aber in fast allen Fällen (kein Wortspiel beabsichtigt) spielt das keine Rolle.
  • Die maximale Länge der Zeichenfolge bei N = 16 in der ursprünglichen Antwort wird in Chrome gemessen. In Firefox ist sie N = 11. Aber wie bereits erläutert, geht es bei der zweiten Lösung um die Unterstützung jeder gewünschten Zeichenfolgenlänge und nicht um das Hinzufügen von Zufälligkeit, so dass es keinen großen Unterschied macht.
  • Alle zurückgegebenen Zeichenketten haben die gleiche Wahrscheinlichkeit, zurückgegeben zu werden, zumindest soweit die von Math.random() zurückgegebenen Ergebnisse gleichmäßig verteilt sind (dies ist in jedem Fall keine kryptographische Zufälligkeit).
  • Es können nicht alle möglichen Zeichenketten der Größe N zurückgegeben werden. Bei der zweiten Lösung ist dies offensichtlich (da die kleinere Zeichenkette einfach dupliziert wird), aber auch bei der ursprünglichen Antwort ist dies der Fall, da bei der Konvertierung zur Basis-36 die letzten paar Bits möglicherweise nicht Teil der ursprünglichen Zufallsbits sind. Wenn Sie sich das Ergebnis von Math.random().toString(36) ansehen, werden Sie feststellen, dass das letzte Zeichen nicht gleichmäßig verteilt ist. In den meisten Fällen spielt das keine Rolle, aber wir schneiden die endgültige Zeichenfolge vom Anfang und nicht vom Ende der Zufallszeichenfolge ab, damit kurze Zeichenfolgen (z. B. N=1) nicht betroffen sind.

Aktualisierung:

Hier sind ein paar andere funktionale Einzeiler, die ich mir ausgedacht habe. Sie unterscheiden sich von der obigen Lösung dadurch, dass:

  • Sie verwenden ein explizites willkürliches Alphabet (das allgemeiner ist und zur ursprünglichen Frage passt, in der sowohl Groß- als auch Kleinbuchstaben verlangt wurden).
  • Alle Zeichenketten der Länge N haben die gleiche Wahrscheinlichkeit, zurückgegeben zu werden (d. h. die Zeichenketten enthalten keine Wiederholungen).
  • Sie basieren auf einer Map-Funktion und nicht auf dem toString(36)-Trick, was sie einfacher und verständlicher macht.

Angenommen, das Alphabet Ihrer Wahl lautet

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Diese beiden sind gleichwertig, so dass Sie sich für das entscheiden können, was für Sie intuitiver ist:

Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');

und

Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');

Editar:

Ich scheine qubyte y Martijn de Milliano hat ähnliche Lösungen wie die letztgenannte gefunden (Hut ab!), die ich irgendwie übersehen habe. Da sie auf den ersten Blick nicht so kurz aussehen, lasse ich sie trotzdem hier, falls jemand wirklich einen Einzeiler braucht :-)

Außerdem habe ich in allen Lösungen "new Array" durch "Array" ersetzt, um ein paar Bytes einzusparen.

0 Stimmen

Warum nicht einfach 1 hinzufügen? (Math.random()+1).toString(36).substring(7);

0 Stimmen

Denn die Hinzufügung von 1 löst keines der beiden hier diskutierten Probleme. Zum Beispiel ergibt (1).toString(36).substring(7) eine leere Zeichenfolge.

0 Stimmen

使用方法 Math.random().toString(36).substring(2,7) führt zu einem erwarteten Ergebnis, das eher der .substring(2, n+2)

160voto

Die kompakteste Lösung, denn slice ist kürzer als substring . Durch die Subtraktion vom Ende der Zeichenkette kann das Fließkomma-Symbol vermieden werden, das von der random Funktion:

Math.random().toString(36).slice(-5);

oder sogar

(+new Date).toString(36).slice(-5);

Aktualisierung: Ein weiterer Ansatz wurde mit btoa Methode:

btoa(Math.random()).slice(0, 5);
btoa(+new Date).slice(-7, -2);
btoa(+new Date).substr(-7, 5);

// Using Math.random and Base 36:
console.log(Math.random().toString(36).slice(-5));

// Using new Date and Base 36:
console.log((+new Date).toString(36).slice(-5));

// Using Math.random and Base 64 (btoa):
console.log(btoa(Math.random()).slice(0, 5));

// Using new Date and Base 64 (btoa):
console.log(btoa(+new Date).slice(-7, -2));
console.log(btoa(+new Date).substr(-7, 5));

0 Stimmen

Math.random().toString(36).slice(-5); - Was wäre, wenn Math.random() gibt zurück. 0.0 ?

0 Stimmen

@x-ray, Sie erhalten "0" ;)

3 Stimmen

Genau. ;) Und wenn Math.random() gibt zurück. 0.5 das Ergebnis ist "0.i" . Ich weiß nicht, ob es noch andere Fälle gibt. Ich wollte nur darauf hinweisen, dass dies keine korrekte Antwort auf die Frage ist (5 Zeichen aus [a-zA-Z0-9]).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X