Generieren Sie zufällige Zeichenfolgen in JavaScript

1780

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

Was ist der beste Weg, dies mit JavaScript zu tun?

Tom Lehman
quelle
48
Warnung: Keine der Antworten hat ein true-randomErgebnis! Sie sind nur pseudo-random. Wenn Sie zufällige Zeichenfolgen zum Schutz oder zur Sicherheit verwenden, verwenden Sie keine davon !!! Versuchen Sie eine dieser APIs
Ron van der Heijden
48
Math.random (). ToString (36) .replace (/ [^ az] + / g, '')
Muaz Khan
13
Bitte setzen Sie die Lösung in eine Lösung.
Chrysss
216
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
Friedrich
12
Hinweis Die HTML5-Webcrypto-Zufalls-API bietet echte Zufälligkeit.
Mikemaccana

Antworten:

2431

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));

csharptest.net
quelle
117
Dies ist in Ordnung für kurze Zeichenfolgen, aber Vorsicht, wenn Sie solche Zeichenfolgen verwenden, +=führt dies zu einem O (n ^ 2) -Verhalten. Wenn Sie längere Zeichenfolgen erstellen möchten, sollten Sie ein Array einzelner Zeichen erstellen und diese am Ende zusammenfügen.
dan_waterworth
97
@ Dan_waterworth Es ist wahrscheinlich in fast jedem Fall egal
Alex Reece
7
@dan_waterworth, Eigentlich +=ist es aus irgendeinem Grund oft schneller, sogar innerhalb von Schleifen verwendet - jsperf.com/join-vs-concatenation
Konrad Borowski
18
@ JonathanPaulson Zeig mir die Zahlen . Siehe den vorherigen Kommentar mit einem jsperf-Link oder jsperf.com/sad-tragedy-of-microoptimization oder sitepen.com/blog/2008/05/09/string-performance-an-analysis usw. Außerdem umfasst diese Frage nur 5 Verkettungen .
Alex Reece
11
@codenamejames Bitte verwenden Sie dies nicht in Ihrem Passwort Salting. Es ist nur pseudozufällig, nicht sicher. Angenommen, Sie verwenden Node (ich bin mir nicht einmal sicher, wo ich anfangen soll, wenn Sie auf der Clientseite salzen), verwenden Sie cryptostattdessen.
Hydrothermal
2330

let r = Math.random().toString(36).substring(7);
console.log("random", r);

Hinweis: Der obige Algorithmus weist die folgenden Schwächen auf:

  • Es werden zwischen 0 und 6 Zeichen generiert, da beim Stringisieren von Gleitkommazahlen nachgestellte Nullen entfernt werden.
  • Dies hängt stark von dem Algorithmus ab, der zum Stringifizieren von Gleitkommazahlen verwendet wird, was fürchterlich komplex ist. (Siehe das Dokument "So drucken Sie Gleitkommazahlen genau" .)
  • Math.random()Abhängig von der Implementierung kann eine vorhersagbare ("zufällig aussehende", aber nicht wirklich zufällige) Ausgabe erzeugt werden. Die resultierende Zeichenfolge ist nicht geeignet, wenn Sie die Eindeutigkeit oder Unvorhersehbarkeit garantieren müssen.
  • Selbst wenn 6 gleichmäßig zufällige, unvorhersehbare Zeichen erzeugt wurden, können Sie aufgrund des Geburtstagsparadoxons erwarten, dass nach dem Generieren von nur etwa 50.000 Zeichenfolgen ein Duplikat angezeigt wird . (sqrt (36 ^ 6) = 46656)
Doppeltipp
quelle
276
Math.random().toString(36).substr(2, 5), weil .substring(7)es länger als 5 Zeichen ist. Volle Punkte, immer noch!
Drache
81
@Scoop Die toStringMethode eines Zahlentyps in Javascript verwendet einen optionalen Parameter, um die Zahl in eine bestimmte Basis umzuwandeln. Wenn Sie beispielsweise zwei übergeben, wird Ihre Nummer binär dargestellt. Ähnlich wie bei hex (Basis 16) verwendet Basis 36 Buchstaben, um Ziffern über 9 hinaus darzustellen. Wenn Sie eine Zufallszahl in Basis 36 konvertieren, erhalten Sie eine Reihe von scheinbar zufälligen Buchstaben und Zahlen.
Chris Baker
76
Sieht wunderschön aus, erzeugt aber in einigen Fällen eine leere Zeichenfolge! Wenn zufällig 0, 0,5, 0,25, 0,125 ... zurückgegeben wird, führt dies zu einer leeren oder kurzen Zeichenfolge.
Gertas
67
@gertas Dies kann vermieden werden durch(Math.random() + 1).toString(36).substring(7);
George Reith
84
Guy, das ist praktisch nutzlos. Führen Sie es nur 1000000 Mal aus, und Sie erhalten im Allgemeinen etwa 110000 Wiederholungsvorkommen: var values ​​= {}, i = 0, duplicateCount = 0, val; while (i <1000000) {val = Math.random (). toString (36) .substring (7); if (values ​​[val]) {duplicateCount ++; } values ​​[val] = 1; i ++; } console.log ("TOTAL DUPLICATES", duplicateCount);
Hacklikecrack
463

Math.random ist schlecht für so etwas

Option 1

Wenn Sie dies serverseitig tun können , verwenden Sie einfach das Kryptomodul -

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

// "bb5dc8842ca31d4603d6aa11448d1654"

Die resultierende Zeichenfolge ist doppelt so lang wie die von Ihnen generierten zufälligen Bytes. Jedes hexadezimal codierte Byte besteht aus 2 Zeichen. 20 Bytes sind 40 hexadezimale Zeichen.


Option 2

Wenn Sie dies clientseitig tun müssen , versuchen Sie es vielleicht mit dem uuid-Modul -

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

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

Option 3

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

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

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


Weitere Informationen zu crypto.getRandomValues-

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

Hier ist 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 die IE11-Unterstützung können Sie Folgendes verwenden:

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

Informationen zur Browserabdeckung finden Sie unter https://caniuse.com/#feat=getrandomvalues

Vielen Dank
quelle
4
Genau. Während eine UUID für die Zuweisung einer ID zu einem Objekt in Ordnung ist, ist die Verwendung als Zeichenfolge aus zufälligen Zeichen aus diesem (und wahrscheinlich auch aus anderen) Gründen keine gute Idee.
Wmassingham
2
Keine Notwendigkeit für .map()Option 3. Array.from(arr, dec2hex).join('')=== Array.from(arr).map(dec2hex).join(''). Vielen Dank, dass Sie mir diese Funktionen vorgestellt haben :-)
Fred Gandt
6
Sie sollten in der Antwort erwähnen, dass Option 2 auch node.js benötigt, um zu funktionieren. Es ist kein reines Javascript.
Esko
5
Dies ist zwar kryptografisch sicherer, erfüllt jedoch nicht die Anforderungen der Frage, da nur 0-9 und af (hexadezimal) und nicht 0-9, az, AZ ausgegeben werden.
QJake
1
Kann das requireModul nicht nur serverseitig verwendet werden?
aJetHorn
173

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).substr(2, 5);
Silberner Ringvee
quelle
9
Was ist, wenn Math.random().toString(36)eine Zahl mit weniger als 5 Zeichen zurückgegeben wird?
Michael Litvin
3
Nun, das ist eine interessante Anklage von @ Aperçu. Ich sage nicht, dass ich die Lösung erfunden habe, aber ich verwende sie seit Jahren in meinen Projekten. Und es hat nichts mit dem Kommentar zu tun, den Sie erwähnt haben. Und ich bin mir ziemlich sicher, dass in SO die nützlichsten Informationen am richtigen Ort wichtig sind und auch wenn sie bereits an einem anderen Ort vorhanden sind. Zum Glück scheinen mindestens 51 Leute diese Antwort nützlich gefunden zu haben. Gern geschehen!
Silver Ringvee
3
Um zu vermeiden, dass bei Math.random () eine leere Zeichenfolge zurückgegeben wird, können Siefunction getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
mikep
5
@rinogo Math.random () kann 0 zurückgeben, aber nicht 1 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
mikep
6
Ich habe diesen Code 1.000.000.000 Mal ausgeführt und trotzdem keine leere Zeichenfolge erhalten: jsfiddle.net/mtp5730r Ich würde sagen, dass Sie ziemlich sicher sind, keine leere Zeichenfolge zu erhalten.
MacroMan
157

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

Erstens, wie andere bereits erwähnt haben, besteht eine geringe Wahrscheinlichkeit, dass kurze Zeichenfolgen oder sogar eine leere Zeichenfolge (wenn die Zufallszahl 0 ist) erzeugt werden, wodurch Ihre Anwendung möglicherweise beschädigt wird. 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. Im Folgenden wird eine Zeichenfolge der Größe N für jedes N zurückgegeben (beachten Sie jedoch, dass die Verwendung von N> 16 die Zufälligkeit nicht erhöht oder 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), dh zwischen 0 (einschließlich) und 1 (exklusiv).
  2. Konvertieren Sie die Zahl in eine Basis-36-Zeichenfolge, dh verwenden Sie die Zeichen 0-9 und az.
  3. Pad mit Nullen (löst das erste Problem).
  4. Schneiden Sie die führende '0' ab. Präfix und zusätzliche Auffüllnullen.
  5. Wiederholen Sie die Zeichenfolge so oft, bis mindestens N Zeichen enthalten sind (indem Sie leere Zeichenfolgen mit der kürzeren zufälligen Zeichenfolge als Trennzeichen verbinden).
  6. Schneiden Sie genau N Zeichen aus der Zeichenfolge.

Weitere Gedanken:

  • Diese Lösung verwendet keine Großbuchstaben, aber in fast allen Fällen (kein Wortspiel beabsichtigt) spielt es keine Rolle.
  • Die maximale Zeichenfolgenlänge bei N = 16 in der ursprünglichen Antwort wird in Chrome gemessen. In Firefox ist es N = 11. Wie bereits erläutert, besteht die zweite Lösung darin, die angeforderte Zeichenfolgenlänge zu unterstützen und nicht die Zufälligkeit hinzuzufügen, sodass es keinen großen Unterschied macht.
  • Alle zurückgegebenen Zeichenfolgen haben die gleiche Wahrscheinlichkeit, zurückgegeben zu werden, zumindest soweit die von Math.random () zurückgegebenen Ergebnisse gleichmäßig verteilt sind (dies ist in keinem Fall eine Zufälligkeit mit kryptografischer Stärke).
  • Möglicherweise werden nicht alle möglichen Zeichenfolgen der Größe N zurückgegeben. In der zweiten Lösung ist dies offensichtlich (da die kleinere Zeichenfolge einfach dupliziert wird), aber auch in der ursprünglichen Antwort gilt dies, da bei der Konvertierung in Basis-36 die letzten paar Bits möglicherweise nicht Teil der ursprünglichen zufälligen Bits sind. Wenn Sie sich das Ergebnis von Math.random (). ToString (36) ansehen, werden Sie feststellen, dass das letzte Zeichen nicht gleichmäßig verteilt ist. Auch hier spielt es in fast allen Fällen keine Rolle, aber wir schneiden die letzte Zeichenfolge eher vom Anfang als vom Ende der zufälligen Zeichenfolge ab, damit kurze Zeichenfolgen (z. B. N = 1) nicht betroffen sind.

Aktualisieren:

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

  • Sie verwenden ein explizites beliebiges Alphabet (allgemeiner und für die ursprüngliche Frage geeignet, bei der sowohl Groß- als auch Kleinbuchstaben angefordert wurden).
  • Alle Zeichenfolgen der Länge N haben die gleiche Wahrscheinlichkeit, zurückgegeben zu werden (dh Zeichenfolgen enthalten keine Wiederholungen).
  • Sie basieren auf einer Kartenfunktion und nicht auf dem Trick toString (36), wodurch sie einfacher und verständlicher werden.

Angenommen, Sie haben das Alphabet Ihrer Wahl

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Dann sind diese beiden gleichwertig, sodass Sie auswählen 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('');

Bearbeiten:

Ich scheine qubyte zu sein und Martijn de Milliano hat ähnliche Lösungen gefunden (Lob!), Die ich irgendwie vermisst habe. Da sie auf einen Blick nicht so kurz aussehen, lasse ich es trotzdem hier, falls jemand wirklich einen Einzeiler will :-)

Außerdem wurde in allen Lösungen 'neues Array' durch 'Array' ersetzt, um ein paar weitere Bytes zu sparen.

Amichair
quelle
Warum nicht einfach 1 hinzufügen? (Math.random()+1).toString(36).substring(7);
Emix
Weil das Hinzufügen von 1 keines der beiden hier diskutierten Probleme löst. Zum Beispiel erzeugt (1) .toString (36) .substring (7) eine leere Zeichenfolge.
Amichair
Die Verwendung Math.random().toString(36).substring(2,7)ergibt ein erwartetes Ergebnis, das eher dem.substring(2, n+2)
Joseph Rex
Array.apply(null, {length: 5}).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('')
Muhammad Umer
Das ist großartig, aber wenn es in Firefox mit N = 16 ausgeführt wird, sind die letzten ~ 6 Ziffern Null ... (Aber es erfüllt den Wunsch des OP nach 5 zufälligen Zeichen.)
Edward Newell
127

Die kompakteste Lösung, weil sie slicekürzer ist als substring. Durch Subtrahieren vom Ende der Zeichenfolge kann das von der randomFunktion erzeugte Gleitkommasymbol vermieden werden :

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

oder auch

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

Update: Ein weiterer Ansatz mit der btoaMethode wurde hinzugefügt :

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));

Valentin Podkamennyi
quelle
Math.random().toString(36).slice(-5);- Was ist, wenn Math.random()zurückkommt 0.0?
Röntgen
@ Röntgen, werden Sie bekommen "0";)
Valentin Podkamennyi
2
Genau. ;) Und wenn Math.random()zurückgegeben wird, ist 0.5das Ergebnis "0.i". Ich bin mir nicht sicher, ob es andere Randfälle gibt. Ich wollte nur darauf hinweisen, dass dies keine korrekte Antwort auf die Frage ist (5 Zeichen aus [a-zA-Z0-9]).
Röntgen
2
@ x-ray, ich werde nicht sagen, dass dies die richtige Antwort ist, ich sage nur, dass dies eine kompakte Version der obigen @ dobletap-Antwort ist. Ich persönlich benutze (+new Date + Math.random()), um diesen Fall zu verhindern. Trotzdem danke für den Hinweis.
Valentin Podkamennyi
1
Diese. Ich weiß nicht, warum andere Antworten so viel Code erfordern
John Ktejik
100

So etwas sollte funktionieren

function randomString(len, charSet) {
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var randomString = '';
    for (var i = 0; i < len; i++) {
        var randomPoz = Math.floor(Math.random() * charSet.length);
        randomString += charSet.substring(randomPoz,randomPoz+1);
    }
    return randomString;
}

Rufen Sie mit dem Standardzeichensatz [a-zA-Z0-9] an oder senden Sie Ihren eigenen:

var randomValue = randomString(5);

var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');
CaffGeek
quelle
Eine Variante des Beispiels hier finden Sie hier: mediacollege.com/internet/javascript/number/random.html
David
1
könnte genauso gut lendirekt in einer whileSchleife dekrementieren
drzaus
Vielen Dank, ich habe gerade unten eine Coffeescript-Variante dieses Beispiels gepostet: stackoverflow.com/a/26682781/262379
Dinis Cruz
Wenn diese öffentlich verwendet werden sollen, sollten Sie wahrscheinlich die Vokale entfernen. Ein bisschen weniger Entropie, aber viel sicherer, da Sie keine Wörter generieren können, die Menschen beleidigen könnten. Deshalb gefällt mir das, da ich meine eigene Zeichenkette einsenden kann. Gut gemacht.
Nate Bunney
Ziemlich hardcore, hat für mich gearbeitet, danke!
Zaki Mohammed
73

Eine neuere Version mit dem es6- Spread-Operator :

[...Array(30)].map(() => Math.random().toString(36)[2]).join('')

  • Das 30ist willkürliche Zahl, können Sie eine beliebige Token Länge holen Sie wollen
  • Das 36ist die maximale radix Nummer , die Sie weitergeben können numeric.toString () , was bedeutet , alle Zahlen und az Kleinbuchstaben
  • Das 2wird verwendet, um den 3. Index aus der zufälligen Zeichenfolge auszuwählen, die so aussieht: "0.mfbiohx64i"Wir könnten jeden Index danach nehmen0.
Oder Duan
quelle
Könntest du erklären? Vor allem, warum Sie 36 an toString () übergeben und warum Sie das 3. Element auswählen?
Vuza
5
Dies ist die beste Lösung
Überwinder
nett, aber diese Lösung enthält keine [AZ] -Zeichen als angeforderte Frage, nur [a-z0-9]
Nahuel Greco
71

function randomstring(L) {
  var s = '';
  var randomchar = function() {
    var n = Math.floor(Math.random() * 62);
    if (n < 10) return n; //1-10
    if (n < 36) return String.fromCharCode(n + 55); //A-Z
    return String.fromCharCode(n + 61); //a-z
  }
  while (s.length < L) s += randomchar();
  return s;
}
console.log(randomstring(5));

kennebec
quelle
Das gefällt mir am besten. Sie können leicht ändern, um zusätzliche Parameter zu akzeptieren und nur Zahlen, Senkungen oder Großbuchstaben zurückzugeben. Ich denke nicht, dass der ultra-komprimierte Stil notwendig istwhile(s.length< L) s+= randomchar();
mastaBlasta
3
Auch while(L--)wird es tun
vsync
1
Verwenden Sie lieber die robustere 'A'.charCodeAt(0)als die magische Zahl 55(und ebenso für die 61). Zumal auf meiner Plattform sowieso die magische Zahl zurückkehrt 65. Dieser Code wird sich auch besser selbst dokumentieren.
Grumdrig
Ich habe hier eine für die Minimierung optimierte (46 Byte kleinere) Variante Ihrer Implementierung erstellt: stackoverflow.com/a/52412162
Waruyama
Viel Glück beim Debuggen dieses @Waruyama. Dafür ist Webpack da!
Dylan Watson
61

Zufälliger String-Generator (Alpha-Numerisch | Alpha | Numerisch)

/**
 * Pseudo-random string generator
 * http://stackoverflow.com/a/27872144/383904
 * Default: return a random alpha-numeric string
 * 
 * @param {Integer} len Desired length
 * @param {String} an Optional (alphanumeric), "a" (alpha), "n" (numeric)
 * @return {String}
 */
function randomString(len, an) {
  an = an && an.toLowerCase();
  var str = "",
    i = 0,
    min = an == "a" ? 10 : 0,
    max = an == "n" ? 10 : 62;
  for (; i++ < len;) {
    var r = Math.random() * (max - min) + min << 0;
    str += String.fromCharCode(r += r > 9 ? r < 36 ? 55 : 61 : 48);
  }
  return str;
}

console.log(randomString(10));      // i.e: "4Z8iNQag9v"
console.log(randomString(10, "a")); // i.e: "aUkZuHNcWw"
console.log(randomString(10, "n")); // i.e: "9055739230"


Während in den obigen Abschnitten zusätzliche Überprüfungen für die gewünschte A / N-, A-, N- Ausgabe verwendet werden, teilen wir sie zum besseren Verständnis auf das Wesentliche (nur alphanumerisch) auf:

  • Erstellen Sie eine Funktion, die ein Argument akzeptiert (gewünschte Länge des zufälligen String-Ergebnisses).
  • Erstellen Sie eine leere Zeichenfolge, var str = "";um zufällige Zeichen zu verketten
  • Erstellen Sierand innerhalb einer Schleife eine Indexnummer von 0 bis 61 (0..9 + A..Z + a..z = 62).
  • Erstellen Sie eine bedingte Logik zum Anpassen /rand Korrigieren (da es 0..61 ist), indem Sie sie um eine Zahl erhöhen (siehe Beispiele unten), um die richtige CharCodeZahl und das zugehörige Zeichen zurückzugewinnen.
  • Innerhalb der Schleife verketten zu straString.fromCharCode( incremented rand )

Stellen wir uns die Bereiche der ASCII-Zeichentabelle vor:

_____0....9______A..........Z______a..........z___________  Character
     | 10 |      |    26    |      |    26    |             Tot = 62 characters
    48....57    65..........90    97..........122           CharCode ranges

Math.floor( Math.random * 62 )gibt einen Bereich von 0..61(was wir brauchen).
Korrigieren wir den Zufall, um die richtigen charCode-Bereiche zu erhalten :

      |   rand   | charCode |  (0..61)rand += fix            = charCode ranges |
------+----------+----------+--------------------------------+-----------------+
0..9  |   0..9   |  48..57  |  rand += 48                    =     48..57      |
A..Z  |  10..35  |  65..90  |  rand += 55 /*  90-35 = 55 */  =     65..90      |
a..z  |  36..61  |  97..122 |  rand += 61 /* 122-61 = 61 */  =     97..122     |

Die bedingte Operation Logik aus der obigen Tabelle:

   rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ;
// rand +=  true  ? (  true   ? 55 else 61 ) else 48 ;

Aus der obigen Erklärung ergibt sich das resultierende alphanumerische Snippet :

function randomString(len) {
  var str = "";                                // String result
  for (var i = 0; i < len; i++) {              // Loop `len` times
    var rand = Math.floor(Math.random() * 62); // random: 0..61
    var charCode = rand += rand > 9 ? (rand < 36 ? 55 : 61) : 48; // Get correct charCode
    str += String.fromCharCode(charCode);      // add Character to str
  }
  return str; // After all loops are done, return the concatenated string
}

console.log(randomString(10)); // i.e: "7GL9F0ne6t"

Oder wenn Sie so wollen:

const randomString = (n, r='') => {
  while (n--) r += String.fromCharCode((r=Math.random()*62|0, r+=r>9?(r<36?55:61):48));
  return r;
};

console.log(randomString(10))

Roko C. Buljan
quelle
33

Der einfachste Weg ist:

(new Date%9e6).toString(36)

Dadurch werden zufällige Zeichenfolgen mit 5 Zeichen basierend auf der aktuellen Zeit generiert. Beispielausgabe ist 4mtxjoder 4mv90oder4mwp1

Das Problem dabei ist, dass, wenn Sie es zweimal in derselben Sekunde aufrufen, dieselbe Zeichenfolge generiert wird.

Der sicherere Weg ist:

(0|Math.random()*9e6).toString(36)

Dadurch wird eine zufällige Zeichenfolge mit 4 oder 5 Zeichen generiert, die immer unterschiedlich ist. Beispielausgabe ist wie 30jzmoder 1r591oder4su1a

In beiden Fällen generiert der erste Teil eine Zufallszahl. Der .toString(36)Teil wandelte die Zahl in eine Base36-Darstellung (alphadezimal) um.

MasqueradeCircus
quelle
Ich bin mir nicht ganz sicher, wie dies die Frage beantwortet. Dies ist eine 7 Jahre alte Frage mit vielen gültigen Antworten. Wenn Sie sich für eine neue Antwort entscheiden, sollten Sie besonders darauf achten, dass Ihre Antwort gut erklärt und dokumentiert wird.
Claies
1
Wenn Sie Date verwenden, warum verwenden Sie es nicht einfach wie (+new Date).toString(36)
folgt
Ich mag Ihre Zufallszahlenlösung, aber 9e6 bietet nur 9 Millionen Möglichkeiten gegenüber den 60,4 Millionen für 5 Ziffern (36 ^ 5), sodass Sie sie ersetzen können (0|Math.random()*6.04e7).toString(36), um sie abzudecken.
Le Droid
1
Ich wollte eine längere zufällige Zeichenfolge mit einer möglichst kurzen Routine (für eine Code-Demo), die nicht kryptografisch erstaunlich sein muss, sondern nur einen schönen zufälligen visuellen "Flaum" erzeugt. Ich mag diese Antwort am besten (deine 2.), also danke. Meine zwei Cent: Ich kann es mit einem Tastendruck weniger kurz schlagen, und es werden normalerweise 13 zufällige Zeichen (ohne Punkt) erzeugt : (Math.random()*1e20).toString(36).
Andrew Willems
Ein Problem, das ich mit dieser Antwort habe, ist, dass es nicht [AZ] verwendet, was zufällig in der ursprünglichen Frage steht.
Benutzerfreundlich
22

Hier sind einige einfache Einzeiler. Ändern Sie new Array(5), um die Länge festzulegen.

Einschließlich 0-9a-z

new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36);})

Einschließlich 0-9a-zA-Z

new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();});
Bendytree
quelle
20

Ich weiß, dass jeder es bereits richtig gemacht hat, aber ich hatte das Gefühl, dass ich es auf die leichteste Art und Weise ausprobieren sollte (leichter Code, keine CPU):

function rand(length, current) {
  current = current ? current : '';
  return length ? rand(--length, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt(Math.floor(Math.random() * 60)) + current) : current;
}

console.log(rand(5));

Es braucht ein bisschen Zeit, um den Kopf herumzureißen, aber ich denke, es zeigt wirklich, wie großartig die Syntax von Javascript ist.

Roderick
quelle
20
Wenn Sie versuchen , den Code kurz zu halten, warum schreiben , current = current ? current : '';wenn Sie schreiben current = current || '';
CaffGeek
9
Da es sich hier um Mikrooptimierung handelt, würde ich vorschlagen, die Variablenzuweisung vollständig zu überspringen, wenn dies nicht erforderlich ist:current || (current = '');
Thomas Heymann,
Der Versuch einer Mikrooptimierung unter Verwendung eines "netten", aber ressourcenschonenden rekursiven Algorithmus macht keinen Sinn :-) Eine for-Schleife ist in Javascript immer noch am besten und schlägt die Rekursion sehr lange, bis wirklich große Fortschritte im Optimierungscode der Laufzeiten erzielt werden.
Mörre
17

Wenn Sie Lodash oder Underscore verwenden , ist das ganz einfach:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
Weinstock
quelle
6
Lodash verwendet_.sampleSize('asdfgh',5).join('')
Marlo
2
Dies ist eigentlich keine gute Lösung, da pro Dokument jedes Zeichen aus einem eindeutigen Index stammt. Das heißt, es ist nicht wirklich zufällig, da kein Charakter jemals wiederholen kann / wird.
random_user_name
16

Um die Anforderung [a-zA-Z0-9] und die Länge = 5 zu erfüllen, verwenden Sie

btoa(Math.random()).substr(5, 5);

Kleinbuchstaben, Großbuchstaben und Zahlen werden angezeigt.

Sergio Cabral
quelle
1
Ich denke, Math.random () könnte zu einem base64-String mit zu wenigen Zeichen führen.
Leif
14

Falls jemand an einem Einzeiler interessiert ist (obwohl er für Ihre Bequemlichkeit nicht als solcher formatiert ist), der den Speicher sofort zuweist (beachten Sie jedoch, dass es für kleine Zeichenfolgen wirklich keine Rolle spielt), gehen Sie wie folgt vor:

Array.apply(0, Array(5)).map(function() {
    return (function(charset){
        return charset.charAt(Math.floor(Math.random() * charset.length))
    }('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));
}).join('')

Sie können 5durch die Länge der gewünschten Zeichenfolge ersetzen . Vielen Dank an @AriyaHidayat in diesem Beitrag für die Lösung der mapFunktion, die nicht mit dem von erstellt wurde Array(5).

Martijn de Milliano
quelle
13
Jedes Javascript-Programm ist ein "
Einzeiler
13

Hier ist die Methode, die ich erstellt habe.
Es wird eine Zeichenfolge erstellt, die sowohl Groß- als auch Kleinbuchstaben enthält.
Außerdem habe ich die Funktion eingefügt, mit der auch eine alphanumerische Zeichenfolge erstellt wird.

Arbeitsbeispiele:
http://jsfiddle.net/greatbigmassive/vhsxs/ (nur Alpha)
http://jsfiddle.net/greatbigmassive/PJwg8/ (alphanumerisch)

function randString(x){
    var s = "";
    while(s.length<x&&x>0){
        var r = Math.random();
        s+= String.fromCharCode(Math.floor(r*26) + (r>0.5?97:65));
    }
    return s;
}

Upgrade Juli 2015
Dies macht dasselbe, ist aber sinnvoller und enthält alle Buchstaben.

var s = "";
while(s.length<x&&x>0){
    v = Math.random()<0.5?32:0;
    s += String.fromCharCode(Math.round(Math.random()*((122-v)-(97-v))+(97-v)));
}
Adam
quelle
Mit dieser Funktion können Sie niemals einen Großbuchstaben größer als 'M' oder einen Kleinbuchstaben kleiner als 'n' erhalten.
erkanyildiz
"Ja wirklich?" Oh! werde es dann wahrscheinlich mehr testen. Hmm, da es sich um eine zufällige Zeichenfolge handelt und es uns egal ist, welche Buchstaben darin enthalten sind (solange sie zufällig sind), macht es immer noch das, was wir wollen, was alles ist, was zählt, aber ja, es wird eine Upgrade, danke.
Adam
12

Angenommen, Sie verwenden Unterstriche, können Sie elegant zufällige Zeichenfolgen in nur zwei Zeilen generieren:

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
tiktak
quelle
6
Dadurch hat der zurückgegebene Wert alle eindeutigen Zeichen. Außerdem ist die Länge der Zeichenfolge auf die mögliche Länge von var begrenzt.
Yefu
10
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
Nahuel Greco
quelle
Einfache, saubere Lösung
Mark Swardstrom
Dies verdient eine größere +1
Walid Ammar
10

Schneller und verbesserter Algorithmus. Garantiert keine Uniform (siehe Kommentare).

function getRandomId(length) {
    if (!length) {
        return '';
    }

    const possible =
        'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let array;

    if ('Uint8Array' in self && 'crypto' in self && length <= 65536) {
        array = new Uint8Array(length);
        self.crypto.getRandomValues(array);
    } else {
        array = new Array(length);

        for (let i = 0; i < length; i++) {
            array[i] = Math.floor(Math.random() * 62);
        }
    }

    let result = '';

    for (let i = 0; i < length; i++) {
        result += possible.charAt(array[i] % 62);
    }

    return result;
}
Jaroslaw
quelle
2
Gute Antwort, aber die Wahrscheinlichkeit ist nicht einheitlich. Es gibt 62 mögliche Zeichen und crypto.getRandomValuesgibt einen von 256 eindeutigen Werten zurück. Da 256 nicht durch 62 geteilt wird, haben Sie am Ende eine etwas höhere Wahrscheinlichkeit, Zeichen AH zu erhalten. Ich denke, die beste Lösung besteht darin, das zu tun, was YouTube getan hat, und dem Zeichensatz nur zwei zusätzliche Zeichen (möglicherweise -und _) hinzuzufügen . Wie auch immer, tolle Arbeit - diese Antwort braucht so viel mehr Liebe :)
TeWu
Hinzufügen - und _ ist eine großartige Idee, da Sie damit das komplette URL-sichere Base64-Set erhalten
Cowbert
8

Das Problem bei der Beantwortung von Fragen zu "Ich brauche zufällige Zeichenfolgen" (in welcher Sprache auch immer) ist, dass praktisch jede Lösung eine fehlerhafte primäre Spezifikation der Zeichenfolgenlänge verwendet . Die Fragen selbst zeigen selten, warum die zufälligen Zeichenfolgen benötigt werden, aber ich würde Sie herausfordern, dass Sie selten zufällige Zeichenfolgen mit einer Länge von beispielsweise 8 benötigen. Sie benötigen ausnahmslos eine Reihe eindeutiger Zeichenfolgen , die beispielsweise als Bezeichner für einen bestimmten Zweck verwendet werden sollen.

Es gibt zwei Möglichkeiten, streng eindeutige Zeichenfolgen zu erhalten: deterministisch (was nicht zufällig ist) und Speichern / Vergleichen (was belastend ist). Was machen wir? Wir geben den Geist auf. Wir gehen stattdessen mit probabilistischer Einzigartigkeit . Das heißt, wir akzeptieren, dass ein gewisses (jedoch geringes) Risiko besteht, dass unsere Saiten nicht eindeutig sind. Hier ist das Verständnis von Kollisionswahrscheinlichkeit und Entropie hilfreich.

Daher werde ich das unveränderliche Bedürfnis so umformulieren, dass einige Zeichenfolgen mit einem geringen Wiederholungsrisiko benötigt werden. Nehmen wir als konkretes Beispiel an, Sie möchten ein Potenzial von 5 Millionen IDs generieren. Sie möchten nicht jede neue Zeichenfolge speichern und vergleichen, und Sie möchten, dass sie zufällig ist, sodass Sie ein gewisses Wiederholungsrisiko akzeptieren. Nehmen wir zum Beispiel ein Risiko von weniger als 1 in einer Billion Wiederholungswahrscheinlichkeit. Also, welche Länge der Saite brauchst du? Nun, diese Frage ist nicht genau spezifiziert, da sie von den verwendeten Zeichen abhängt. Aber was noch wichtiger ist, es ist falsch. Was Sie brauchen, ist eine Angabe der Entropie der Saiten, nicht ihrer Länge. Die Entropie kann in direktem Zusammenhang mit der Wahrscheinlichkeit einer Wiederholung in einer bestimmten Anzahl von Zeichenfolgen stehen. Stringlänge kann nicht.

Und hier kann eine Bibliothek wie EntropyString helfen. So generieren Sie zufällige IDs mit einer Wahrscheinlichkeit von weniger als 1 in einer Billion Wiederholungen in 5 Millionen Zeichenfolgen mit entropy-string:

import {Random, Entropy} from 'entropy-string'

const random = new Random()
const bits = Entropy.bits(5e6, 1e12)

const string = random.string(bits)

44hTNghjNHGGRHqH9

entropy-stringVerwendet standardmäßig einen Zeichensatz mit 32 Zeichen. Es gibt andere vordefinierte Zeichensätze, und Sie können auch Ihre eigenen Zeichen angeben. Beispiel: Generieren von IDs mit derselben Entropie wie oben, jedoch unter Verwendung von Hex-Zeichen:

import {Random, Entropy, charSet16} from './entropy-string'

const random = new Random(charSet16)
const bits = Entropy.bits(5e6, 1e12)

const string = random.string(bits)

27b33372ade513715481f

Beachten Sie den Unterschied in der Zeichenfolgenlänge aufgrund des Unterschieds in der Gesamtzahl der Zeichen im verwendeten Zeichensatz. Das Risiko einer Wiederholung in der angegebenen Anzahl potenzieller Zeichenfolgen ist gleich. Die Stringlängen sind nicht. Und das Beste ist, dass das Wiederholungsrisiko und die potenzielle Anzahl von Zeichenfolgen explizit sind. Kein Raten mehr mit Stringlänge.

Dingo Himmel
quelle
7
function randomString (strLength, charSet) {
    var result = [];

    strLength = strLength || 5;
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    while (--strLength) {
        result.push(charSet.charAt(Math.floor(Math.random() * charSet.length)));
    }

    return result.join('');
}

Dies ist so sauber wie es nur geht. Es ist auch schnell, http://jsperf.com/ay-random-string .

Gajus
quelle
Für mich erzeugt dies immer zufällige Zeichenfolgen mit strLength - 1: - /
Xanderiel
3
Das Wechseln von --strLengthzu strLength--behebt es für mich.
Xanderiel
7

Sie können ein Array von Elementen durchlaufen und diese rekursiv zu einer Zeichenfolgenvariablen hinzufügen, z. B. wenn Sie eine zufällige DNA-Sequenz wünschen:

function randomDNA(len) {
  len = len || 100
  var nuc = new Array("A", "T", "C", "G")
  var i = 0
  var n = 0
  s = ''
  while (i <= len - 1) {
    n = Math.floor(Math.random() * 4)
    s += nuc[n]
    i++
  }
  return s
}

console.log(randomDNA(5));

Andy
quelle
6

Ich habe keine saubere Lösung gefunden, um sowohl Klein- als auch Großbuchstaben zu unterstützen.

Unterstützung nur für Kleinbuchstaben:

Math.random().toString(36).substr(2, 5)

Aufbauend auf dieser Lösung zur Unterstützung von Klein- und Großbuchstaben:

Math.random().toString(36).substr(2, 5).split('').map(c => Math.random() < 0.5 ? c.toUpperCase() : c).join('');

Ändern Sie die 5insubstr(2, 5) der Länge einstellen Sie benötigen.

Ravishi
quelle
6

Einzeiler:

Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
Andrew
quelle
Um es kürzer zu machen, ändern Sie das Argument in Array(15)einen kleineren Wert. ZB : Array(4).
Andrew
Ich liebe diese Lösung wirklich, einfach und klar. Es werden 15 Zufallszahlen zwischen 0 und 1 generiert, die Hexadezimalzahl generiert und dann die ersten beiden Zeichen entfernt. Schließlich werden alle zusammengeführt.
Siscia
5

Das funktioniert sicher

<script language="javascript" type="text/javascript">
function randomString() {
 var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
 var string_length = 8;
 var randomstring = '';
 for (var i=0; i<string_length; i++) {
  var rnum = Math.floor(Math.random() * chars.length);
  randomstring += chars.substring(rnum,rnum+1);
 }
 document.randform.randomfield.value = randomstring;
}
</script>
Vignesh
quelle
5

Wie wäre es mit so etwas: Date.now().toString(36) Nicht sehr zufällig, aber kurz und jedes Mal, wenn Sie es anrufen, ziemlich einzigartig.

Swergas
quelle
1
Leider ist dies nicht eindeutig, da Date.now()nur eine Millisekundenauflösung vorliegt. Wenn Sie beispielsweise in einer einfachen Schleife ausgeführt werden, erhalten Sie viele Duplikate. for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }.
Nate
5

Groß- und Kleinschreibung wird nicht berücksichtigt. Alphanumerische Zeichen:

function randStr(len) {
  let s = '';
  while (s.length < len) s += Math.random().toString(36).substr(2, len - s.length);
  return s;
}

// usage
console.log(randStr(50));

Der Vorteil dieser Funktion besteht darin, dass Sie zufällige Zeichenfolgen unterschiedlicher Länge erhalten können und die Länge der Zeichenfolge sichergestellt wird.

Groß- und Kleinschreibung beachten Alle Zeichen:

function randStr(len) {
  let s = '';
  while (len--) s += String.fromCodePoint(Math.floor(Math.random() * (126 - 33) + 33));
  return s;
}

// usage
console.log(randStr(50));

Benutzerdefinierte Zeichen

function randStr(len, chars='abc123') {
  let s = '';
  while (len--) s += chars[Math.floor(Math.random() * chars.length)];
  return s;
}

// usage
console.log(randStr(50));
console.log(randStr(50, 'abc'));
console.log(randStr(50, 'aab')); // more a than b

Ali
quelle
Diese Antwort passt besser zu meinem Anwendungsfall. Es wäre cool, wenn Sie var possibleder akzeptierten Antwort ein "Gefällt mir" hinzufügen könnten , damit das Ergebnis der Funktion besser konfigurierbar ist.
Denis.Sabolotni
4

Generieren Sie eine 10 Zeichen lange Zeichenfolge. Die Länge wird durch einen Parameter eingestellt (Standard 10).

function random_string_generator(len) {
var len = len || 10;
var str = '';
var i = 0;

for(i=0; i<len; i++) {
    switch(Math.floor(Math.random()*3+1)) {
        case 1: // digit
            str += (Math.floor(Math.random()*9)).toString();
        break;

        case 2: // small letter
            str += String.fromCharCode(Math.floor(Math.random()*26) + 97); //'a'.charCodeAt(0));
        break;

        case 3: // big letter
            str += String.fromCharCode(Math.floor(Math.random()*26) + 65); //'A'.charCodeAt(0));
        break;

        default:
        break;
    }
}
return str;
}
ropsiU
quelle
4

Sie können Coderain verwenden . Es ist eine Bibliothek, um zufällige Codes nach einem bestimmten Muster zu generieren. Verwendung #als Platzhalter für Groß- und Kleinbuchstaben sowie Ziffern:

var cr = new CodeRain("#####");
console.log(cr.next());

Es gibt andere Platzhalter wie Afür Großbuchstaben oder 9für Ziffern.

Was nützlich sein kann, ist, dass ein Anruf .next()immer ein eindeutiges Ergebnis liefert, sodass Sie sich nicht um Duplikate kümmern müssen.

Hier ist eine Demo-Anwendung, die eine Liste eindeutiger Zufallscodes generiert .

Vollständige Offenlegung: Ich bin der Autor von Coderain.

Lukasz Wiktor
quelle
NEIN NEIN NEIN - Verwenden Sie native Methoden.