Générer des chaînes / caractères aléatoires en JavaScript

Je veux une chaîne de 5 caractères composée de caractères sélectionnés au hasard dans l'ensemble [a-zA-Z0-9] .

Quelle est la meilleure façon de le faire avec JavaScript?

Je pense que cela fonctionnera pour vous:

 function makeid() { var text = ""; var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; for (var i = 0; i < 5; i++) text += possible.charAt(Math.floor(Math.random() * possible.length)); return text; } console.log(makeid()); 
 Math.random().toString(36).substring(7); 

Math.random est mauvais pour ce genre de chose

Option 1

Si vous êtes en mesure de faire ce côté serveur , utilisez le module crypto

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

La chaîne résultante sera deux fois plus longue que les octets aléatoires générés; Chaque octet codé en hexadécimal est de 2 caractères. 20 octets seront 40 caractères d'hex.


Option 2

Si vous devez le faire côté client , essayez peut-être le module uuid

 var uuid = require("uuid"); var id = uuid.v4(); // "110ec58a-a0f2-4ac4-8393-c866d813b8d1" 

Option 3

Si vous devez faire ce client côté et vous ne devez pas supporter les anciens navigateurs, vous pouvez le faire sans dépendances

 // dec2hex :: Integer -> String 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" 

Voici une amélioration de l'excellente réponse de Doubletap . L'original a deux inconvénients abordés ici:

Tout d'abord, comme d'autres l'ont mentionné, il existe une faible probabilité de produire des chaînes courtes ou même une chaîne vide (si le nombre aléatoire est 0), ce qui risque de briser votre application. Voici une solution:

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

Deuxièmement, l'original et la solution ci-dessus limitent la taille de la chaîne N à 16 caractères. Ce qui suit renverra une chaîne de taille N pour tout N (mais notez que l'utilisation de N> 16 n'augmentera pas le caractère aléatoire ou diminuera la probabilité de collisions):

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

Explication:

  1. Choisissez un nombre aléatoire dans la plage [0,1], c'est-à-dire entre 0 (inclus) et 1 (exclusif).
  2. Convertissez le nombre en une base-36, c'est-à-dire en utilisant les caractères 0-9 et az.
  3. Pad avec des zéros (résout le premier problème).
  4. Couper le premier '0.' Préfixe et zéros de rembourrage supplémentaires.
  5. Répétez la chaîne suffisamment de temps pour avoir au moins N caractères (en joignant des chaînes vides avec la chaîne aléatoire plus courte utilisée comme délimiteur).
  6. Tranchez exactement N caractères de la chaîne.

Autres pensées:

  • Cette solution n'utilise pas de lettres majuscules, mais dans presque tous les cas (sans jeu de mots), cela n'a pas d'importance.
  • La longueur de chaîne maximale à N = 16 dans la réponse d'origine est mesurée en Chrome. Dans Firefox, c'est N = 11. Mais, comme expliqué, la deuxième solution consiste à supporter toute longueur de chaîne requise, et non à ajouter un caractère aléatoire, donc cela ne fait pas grand-chose.
  • Toutes les chaînes renvoyées ont une probabilité égale d'être renvoyées, au moins dans la mesure où les résultats renvoyés par Math.random () sont uniformément répartis (ce n'est en aucun cas un azar de la puissance cryptographique).
  • Toutes les chaînes possibles de taille N ne peuvent pas être retournées. Dans la deuxième solution, cela est évident (puisque la chaîne plus petite est simplement en double), mais aussi dans la réponse d'origine, cela est vrai puisque dans la conversion à la base 36, les derniers bits peuvent ne pas faire partie des bits aléatoires d'origine. Plus précisément, si vous regardez le résultat de Math.random (). ToString (36), vous remarquerez que le dernier caractère n'est pas uniformément réparti. Encore une fois, dans presque tous les cas, cela n'a pas d'importance, mais nous coupons la chaîne finale du début plutôt que la fin de la chaîne aléatoire afin que les chaînes courtes (p. Ex. N = 1) ne soient pas affectées.

Mettre à jour:

Voici quelques autres types de style fonctionnel que j'ai vus. Ils diffèrent de la solution ci-dessus en ce sens:

  • Ils utilisent un alphabet arbitraire explicite (plus générique et adapté à la question initiale qui a demandé des lettres majuscules et minuscules).
  • Toutes les chaînes de longueur N ont une probabilité égale d'être renvoyées (c'est-à-dire que les chaînes ne contiennent pas de répétitions).
  • Ils sont basés sur une fonction de carte, plutôt que sur l'astuce toString (36), ce qui les rend plus simples et faciles à comprendre.

Alors, dites que votre alphabet de choix est

 var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 

Ensuite, ces deux sont équivalents l'un de l'autre, de sorte que vous pouvez choisir ce qui vous est plus intuitif:

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

et

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

Modifier:

Je suis comme Quoyte et Martijn de Milliano a trouvé des solutions similaires à celles-ci (félicitations!), Ce qui me manquait. Comme ils n'ont pas l'air aussi courts d'un coup d'oeil, je vais le laisser ici de toute façon au cas où quelqu'un voudrait vraiment un one-liner 🙂

De plus, a remplacé 'new Array' par 'Array' dans toutes les solutions pour supprimer quelques autres octets.

Court et facile + renvoie exactement 5 caractères aléatoires, par opposition à certaines des réponses les mieux notées trouvées ici.

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

Quelque chose comme ça devrait fonctionner

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

Appelez avec le jeu de caractères par défaut [a-zA-Z0-9] ou envoyez le vôtre:

 var randomValue = randomString(5); var randomValue = randomString(5, 'PICKCHARSFROMTHISSET'); 
 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); //AZ return String.fromCharCode(n + 61); //az } while (s.length < L) s += randomchar(); return s; } console.log(randomstring(5)); 

Générateur de chaîne aléatoire (Alpha-Numeric | Alpha | Numeric)

 /** * RANDOM STRING GENERATOR * * Info: http://stackoverflow.com/a/27872144/383904 * Use: randomString(length [,"A"] [,"N"] ); * Default: return a random alpha-numeric string * Arguments: If you use the optional "A", "N" flags: * "A" (Alpha flag) return random aZ string * "N" (Numeric flag) return random 0-9 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; } 
 randomString(10); // "4Z8iNQag9v" randomString(10, "A"); // "aUkZuHNcWw" randomString(10, "N"); // "9055739230" 

S'amuser. Démo jsBin


Bien que ce qui précède utilise des vérifications supplémentaires pour la sortie souhaitée (A / N, A, N), décrochez-le sur l'essentiel (Alpha-Numeric uniquement) pour une meilleure compréhension:

  • Créez une fonction qui accepte un argument (longueur souhaitée du résultat de chaîne aléatoire)
  • Créez une chaîne vide comme var str = ""; Concaténer des caractères aléatoires
  • À l'intérieur d'une boucle, créez un nombre d'index rand de 0 à 61 (0..9 + A..Z + a..z = 62)
  • Créez une logique conditionnelle pour Ajuster / fixer rand (puisque c'est 0..61) en l'incrémentant par un certain nombre (voir les exemples ci-dessous) pour récupérer le numéro de CharCode droit et le Caractère associé.
  • À l'intérieur de la boucle concaténée à str String.fromCharCode( incremented rand )

Imaginons la table de caractères et leurs plages :

 _____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 ) donne une portée de 0..61 (ce dont nous avons besoin). Comment réparer (incrémenter) le hasard pour obtenir les plages charCode correctes?

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

La logique d' exploitation conditionnelle du tableau ci-dessus:

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

Si vous avez suivi l'explication ci-dessus, vous devriez pouvoir créer cet extrait alphanumérique :

Démo jsBin

 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) ); // "7GL9F0ne6t" 

Ou si vous voulez:

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

La solution la plus compacte, car la slice est plus courte que la substring . En soustrayant de la fin de la chaîne, il est possible d'éviter le symbole de virgule flottante généré par random fonction random :

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

ou même

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

Le moyen le plus simple est:

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

Cela génère des chaînes aléatoires de 5 caractères en fonction de l'heure actuelle. La sortie d'exemple est 4mtxj ou 4mv90 ou 4mwp1

Le problème est que si vous l'appelez deux fois sur la même seconde, cela générera la même chaîne.

Le moyen le plus sûr est:

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

Cela générera une chaîne aléatoire de 4 ou 5 caractères, toujours différente. La sortie d'exemple est comme 30jzm ou 1r591 ou 4su1a

Dans les deux sens, la première partie génère un nombre aléatoire. La partie .toString(36) jette le numéro à une base36 (alphavalmique) de la représentation de celui-ci.

Voici quelques doublures faciles. Changez le new Array(5) pour définir la longueur.

Y compris 0-9a-z

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

Y compris 0-9a-zA-Z

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

Je sais que tout le monde l'a bien compris, mais j'ai eu envie de passer à celui-ci de la manière la plus légère possible (éclairage sur le code, pas 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)); 

Si vous utilisez Lodash ou Underscore , il est si simple:

 var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join(''); 

Voici la méthode que j'ai créée.
Il créera une chaîne contenant des caractères majuscules et minuscules.
En plus, j'ai inclus la fonction qui créera une chaîne alphanumérique aussi.

Exemples de travail:
http://jsfiddle.net/greatbigmassive/vhsxs/ (alpha uniquement)
http://jsfiddle.net/greatbigmassive/PJwg8/ (alphanumérique)

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

Mise à jour juillet 2015
Cela fait la même chose mais a plus de sens et comprend toutes les lettres.

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

Dans le cas où quelqu'un est intéressé par un one-liner (mais pas formaté en tant que tel pour votre commodité) qui alloue la mémoire à la fois (mais notez que pour les petites chaînes, cela n'a vraiment pas d'importance) voici comment le faire:

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

Vous pouvez remplacer 5 par la longueur de la chaîne souhaitée. Merci à @AriyaHidayat dans cette publication pour la solution à la fonction de la map ne fonctionnant pas sur le réseau dispersé créé par Array(5) .

En supposant que vous utilisez underscorejs, il est possible de générer de manière élégante des chaînes aléatoires en deux lignes seulement:

 var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var random = _.sample(possible, 5).join(''); 

Vous pouvez parcourir un ensemble d'éléments et les ajouter récursivement à une variable de chaîne, par exemple si vous voulez une séquence d'ADN aléatoire:

 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)); 
 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(''); } 

C'est aussi propre qu'il obtiendra. C'est aussi rapide, http://jsperf.com/ay-random-string .

Cela fonctionne bien

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

Générer une chaîne de 10 caractères. La longueur est définie par paramètre (par défaut 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; } 

Voici un script de test pour la réponse # 1 (merci @ csharptest.net)

Le script exécute makeid() 1 million fois et, comme vous pouvez le voir, 5 n'est pas très unique. L'exécuter avec une longueur de char de 10 est assez fiable. Je l'ai parcouru environ 50 fois et je n'ai pas encore vu un duplicata :-)

Note: la limite de taille de la pile de noeuds dépasse environ 4 millions d'euros, de sorte que vous ne pouvez pas exécuter ce 5 millions de fois qu'il ne finira jamais.

 function makeid() { var text = ""; var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; for( var i=0; i < 5; i++ ) text += possible.charAt(Math.floor(Math.random() * possible.length)); return text; } ids ={} count = 0 for (var i = 0; i < 1000000; i++) { tempId = makeid(); if (typeof ids[tempId] !== 'undefined') { ids[tempId]++; if (ids[tempId] === 2) { count ++; } count++; }else{ ids[tempId] = 1; } } console.log("there are "+count+ ' duplicate ids'); 

Qu'en est-il de cette petite astuce compacte?

 var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var stringLength = 5; function pickRandom() { return possible[Math.floor(Math.random() * possible.length)]; } var randomString = Array.apply(null, Array(stringLength)).map(pickRandom).join(''); 

Vous avez besoin de Array.apply là pour tromper le tableau vide en étant un ensemble d'indéfinis.

Si vous codiez ES2015, la construction du tableau est un peu plus simple:

 var randomString = Array.from({ length: stringLength }, pickRandom).join(''); 

Algorithme rapide et amélioré. Ne garantit pas l'uniforme (voir les commentaires).

 function getRandomId(length) { if (!length) { return ''; } const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; 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); } } for (let i = 0; i < length; i++) { result += possible.charAt(array[i] % 62); } return result; } 

Élargir l'exemple élégant de Doubletap en répondant aux problèmes émanés de Gertas et Dragon. Il suffit d'ajouter une boucle while pour tester les circonstances nulles rares et limiter les caractères à cinq.

 function rndStr() { x=Math.random().toString(36).substring(7).substr(0,5); while (x.length!=5){ x=Math.random().toString(36).substring(7).substr(0,5); } return x; } 

Voici un jsfiddle vous alertant avec un résultat: http://jsfiddle.net/pLJJ7/

 "12345".split('').map(function(){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(62*Math.random()));}).join(''); //or String.prototype.rand = function() {return this.split('').map(function(){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(62*Math.random()));}).join('');}; 

Générera une chaîne alpha-numérique aléatoire avec la longueur de la première chaîne / appel

C'est ce que j'ai utilisé. Une combinaison d'un couple ici. Je l'utilise dans une boucle, et chaque identifiant qu'elle produit est unique. Il se peut qu'il contienne quelques imprécisions par rapport à l'original.

 var newId = "randomid_" + (Math.random() / +new Date()).toString(36).replace(/[^az]+/g, ''); 

Si une bibliothèque est une possibilité, Chance.js pourrait être utile: http://chancejs.com/#string

J'ai adoré la brève réponse de Math.random () .SString (36) .substring (7) de doubletap, mais pas qu'il ait eu tant de collisions que hacklikecrack a bien souligné. Il a généré des cordes 11-chacter, mais a un taux de duplication de 11% dans une taille d'échantillon de 1 million.

Voici une alternative plus longue (mais encore courte) et plus lente qui n'avait que 133 doubles dans un espace d'échantillonnage de 1 million. Dans de rares cas, la chaîne sera encore inférieure à 11 caractères:

 Math.abs(Math.random().toString().split('') .reduce(function(p,c){return (p<<5)-p+c})).toString(36).substr(0,11); 

Une approche fonctionnelle. Cette réponse n'est pratique que si les conditions préalables fonctionnelles peuvent être exploitées dans d'autres parties de votre application. La performance est probablement une ordure, mais c'était très amusant à écrire.

 // functional prerequisites const U = f=> f (f) const Y = U (h=> f=> f (x=> h (h) (f) (x))) const comp = f=> g=> x=> f (g (x)) const foldk = Y (h=> f=> y=> ([x, ...xs])=> x === undefined ? y : f (y) (x) (y=> h (f) (y) (xs))) const fold = f=> foldk (y=> x=> k=> k (f (y) (x))) const map = f=> fold (y=> x=> [...y, f (x)]) ([]) const char = x=> String.fromCharCode(x) const concat = x=> y=> y.concat(x) const concatMap = f=> comp (fold (concat) ([])) (map (f)) const irand = x=> Math.floor(Math.random() * x) const sample = xs=> xs [irand (xs.length)] // range : make a range from x to y; [x...y] // Number -> Number -> [Number] const range = Y (f=> r=> x=> y=> x > y ? r : f ([...r, x]) (x+1) (y) ) ([]) // srand : make random string from list or ascii code ranges // [(Range a)] -> Number -> [a] const srand = comp (Y (f=> z=> rs=> x=> x === 0 ? z : f (z + sample (rs)) (rs) (x-1) ) ([])) (concatMap (map (char))) // idGenerator : make an identifier of specified length // Number -> String const idGenerator = srand ([ range (48) (57), // include 0-9 range (65) (90), // include AZ range (97) (122) // include az ]) console.log (idGenerator (6)) //=> TT688X console.log (idGenerator (10)) //=> SzaaUBlpI1 console.log (idGenerator (20)) //=> eYAaWhsfvLDhIBID1xRh 

You can use coderain . It's a library to generate random codes according to given pattern. Use # as a placeholder for upper and lowercase characters as well as digits:

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

There are other placeholders like A for uppercase letters or 9 for digits.

What may be useful is that calling .next() will always give you a unique result so you don't have to worry about duplicates.

Here is a demo application that generates a list of unique random codes .

Full disclosure: I'm the author of coderain.