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

1781

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

Quelle est la meilleure façon de procéder avec JavaScript?

Tom Lehman
la source
48
Attention: aucune des réponses n'a de true-randomrésultat! Ils le sont seulement pseudo-random. Lorsque vous utilisez des chaînes aléatoires pour la protection ou la sécurité, n'utilisez aucune d'entre elles !!! Essayez l'une de ces API: random.org
Ron van der Heijden
48
Math.random (). ToString (36) .replace (/ [^ az] + / g, '')
Muaz Khan
13
Veuillez mettre la solution dans une solution.
chryss
216
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
Friedrich
12
Remarque L'API aléatoire Webcrypto HTML5 fournit un réel caractère aléatoire.
mikemaccana

Réponses:

2437

Je pense que cela fonctionnera pour vous:

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
la source
117
C'est très bien pour les chaînes courtes, mais attention, l'utilisation +=de chaînes comme celle-ci entraîne un comportement O (n ^ 2). Si vous souhaitez créer des chaînes plus longues, vous devez créer un tableau de caractères individuels et les réunir à la fin.
dan_waterworth
97
@dan_waterworth Cela n'a probablement pas d'importance dans presque tous les cas: codinghorror.com/blog/2009/01/…
Alex Reece
7
@dan_waterworth, en fait, +=est souvent plus rapide pour une raison quelconque, même utilisé à l'intérieur des boucles - jsperf.com/join-vs-concatenation
Konrad Borowski
18
@JonathanPaulson Montrez-moi les chiffres . Voir le commentaire précédent avec un lien jsperf ou jsperf.com/sad-tragedy-of-microoptimization ou sitepen.com/blog/2008/05/09/string-performance-an-analysis etc. De plus, cette question ne concerne que 5 concaténations .
Alex Reece
11
@codenamejames Veuillez ne pas utiliser ceci dans votre salage de mot de passe. Ce n'est que pseudo-aléatoire non sécurisé. En supposant que vous utilisez Node (je ne sais même pas par où commencer si vous salez du côté client), utilisez cryptoplutôt.
Hydrothermal
2331

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

Remarque: l'algorithme ci-dessus présente les faiblesses suivantes:

  • Il générera n'importe où entre 0 et 6 caractères en raison du fait que les zéros de fin sont supprimés lors de la chaîne des points flottants.
  • Cela dépend profondément de l'algorithme utilisé pour stringifier les nombres à virgule flottante, qui est horriblement complexe. (Voir le document "Comment imprimer des nombres à virgule flottante avec précision" .)
  • Math.random()peut produire une sortie prévisible ("d'aspect aléatoire" mais pas vraiment aléatoire) selon l'implémentation. La chaîne résultante ne convient pas lorsque vous devez garantir l'unicité ou l'imprévisibilité.
  • Même s'il produisait 6 caractères uniformément aléatoires et imprévisibles, vous pouvez vous attendre à voir un doublon après avoir généré seulement environ 50 000 chaînes, en raison du paradoxe d'anniversaire . (sqrt (36 ^ 6) = 46656)
tapez deux fois
la source
276
Math.random().toString(36).substr(2, 5), car .substring(7)elle fait plus de 5 caractères. Plein de points, quand même!
dragon
81
@Scoop La toStringméthode d'un type de nombre en javascript prend un paramètre facultatif pour convertir le nombre en une base donnée. Si vous passez deux, par exemple, vous verrez votre nombre représenté en binaire. Semblable à hex (base 16), la base 36 utilise des lettres pour représenter les chiffres au-delà de 9. En convertissant un nombre aléatoire en base 36, vous vous retrouverez avec un tas de lettres et de chiffres apparemment aléatoires.
Chris Baker
76
C'est beau, mais dans certains cas, cela génère une chaîne vide! Si aléatoire renvoie 0, 0,5, 0,25, 0,125 ..., la chaîne sera vide ou courte.
gertas
68
@gertas Cela peut être évité par(Math.random() + 1).toString(36).substring(7);
George Reith
84
Guy, c'est pratiquement inutile. Exécutez-le seulement 1000000 fois et vous obtenez généralement environ 110000 occurrences de répétition: var values ​​= {}, i = 0, duplicateCount = 0, val; while (i <1000000) {val = Math.random (). toString (36) .substring (7); if (valeurs [val]) {duplicateCount ++; } valeurs [val] = 1; i ++; } console.log ("TOTAL DUPLICATES", duplicateCount);
hacklikecrack
463

Math.random est mauvais pour ce genre de chose

Option 1

Si vous êtes en mesure de le faire côté serveur , utilisez simplement 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 que vous générez; chaque octet codé en hexadécimal est de 2 caractères. 20 octets correspondront à 40 caractères hexadécimaux.


Option 2

Si vous devez faire cela 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 le faire côté client et que vous n'avez pas à prendre en charge les anciens navigateurs, vous pouvez le faire sans dépendances -

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


Pour plus d'informations sur crypto.getRandomValues-

La crypto.getRandomValues()méthode vous permet d'obtenir des valeurs aléatoires cryptographiquement fortes. Le tableau donné comme paramètre est rempli de nombres aléatoires (aléatoire dans sa signification cryptographique).

Voici un petit exemple de console -

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

Pour le support IE11, vous pouvez utiliser -

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

Pour la couverture du navigateur, voir https://caniuse.com/#feat=getrandomvalues

Je vous remercie
la source
4
Exactement. Bien qu'un UUID soit approprié pour attribuer un ID à une chose, l'utiliser comme une chaîne de caractères aléatoires n'est pas une excellente idée pour cette raison (et probablement d'autres).
wmassingham
2
Pas besoin de l' .map()option 3. Array.from(arr, dec2hex).join('')=== Array.from(arr).map(dec2hex).join(''). Merci de m'avoir présenté ces fonctionnalités :-)
Fred Gandt
6
Vous devez mentionner dans la réponse que l'option 2 a également besoin de node.js pour fonctionner, ce n'est pas du pur javascript.
Esko
5
Tout en étant plus sécurisé cryptographiquement, cela ne répond pas réellement aux exigences de la question car il ne génère que 0-9 et af (hexadécimal), et non 0-9, az, AZ.
qJake
1
Le requiremodule n'est-il pas uniquement utilisable côté serveur?
aJetHorn
173

Court, facile et fiable

Renvoie exactement 5 caractères aléatoires, contrairement à certaines des meilleures réponses trouvées ici.

Math.random().toString(36).substr(2, 5);
Argent Ringvee
la source
9
Que se passe-t-il si Math.random().toString(36)renvoie un nombre de moins de 5 caractères?
Michael Litvin
3
Eh bien, c'est un acte d'accusation intéressant de @ Aperçu, je ne dis pas que j'ai inventé la solution mais je l'utilise dans mes projets depuis des années maintenant. Et cela n'a rien à voir avec le commentaire que vous avez mentionné. Et je suis tout à fait sûr qu'en SO, ce qui compte, ce sont les informations les plus utiles au bon endroit et même si elles existent déjà ailleurs. Heureusement, il semble qu'au moins 51 gars ont trouvé cette réponse utile, vous êtes les bienvenus!
Silver Ringvee
3
Pour éviter d'obtenir une chaîne vide dans le cas où Math.random () renvoie 0, vous pouvez utiliserfunction getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
mikep
5
@rinogo Math.random () peut renvoyer 0 mais pas 1 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
mikep
6
J'ai exécuté ce code 1 000 000 000 fois et je n'ai toujours pas obtenu de chaîne vide: jsfiddle.net/mtp5730r Je dirais que vous êtes assez sûr d'obtenir une chaîne vide.
MacroMan
157

Voici une amélioration de l'excellente réponse de doubletap . L'original présente deux inconvénients qui sont abordés ici:

Tout d'abord, comme d'autres l'ont mentionné, il a 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 peut casser 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 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 ne diminuera pas 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 chaîne de 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. Coupez le premier 0. préfixe et zéros supplémentaires.
  5. Répétez la chaîne suffisamment de fois 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. Découpez exactement N caractères de la chaîne.

Réflexions supplémentaires:

  • 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 dans Chrome. Dans Firefox, c'est N = 11. Mais comme expliqué, la deuxième solution consiste à prendre en charge toute longueur de chaîne demandée, pas à ajouter de l'aléatoire, donc cela ne fait pas beaucoup de différence.
  • Toutes les chaînes retournées ont une probabilité égale d'être retournées, au moins dans la mesure où les résultats retournés par Math.random () sont uniformément distribués (ce n'est pas un hasard de force cryptographique, en tout cas).
  • Toutes les chaînes possibles de taille N ne peuvent pas être retournées. Dans la deuxième solution, cela est évident (puisque la plus petite chaîne est simplement dupliquée), mais aussi dans la réponse d'origine, cela est vrai car dans la conversion en 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 réparti uniformément. 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 de la fin de la chaîne aléatoire afin que les chaînes courtes (par exemple N = 1) ne soient pas affectées.

Mise à jour:

Voici quelques autres monoplaces de style fonctionnel que j'ai imaginées. Ils diffèrent de la solution ci-dessus en ce que:

  • Ils utilisent un alphabet arbitraire explicite (plus générique et adapté à la question d'origine qui demandait à la fois des majuscules et des 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 aucune répétition).
  • 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.

Donc, disons que votre alphabet de choix est

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Ensuite, ces deux sont équivalents, vous pouvez donc choisir celui qui vous convient le mieux:

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

Éditer:

Il me semble que Qubyte et Martijn de Milliano ont trouvé des solutions similaires à celles-ci (bravo!), Que j'ai en quelque sorte ratées. Comme ils ne sont pas aussi courts en un coup d'œil, je vais le laisser ici de toute façon au cas où quelqu'un voudrait vraiment un one-liner :-)

En outre, remplacé «nouveau tableau» par «tableau» dans toutes les solutions pour raser quelques octets de plus.

amichair
la source
Pourquoi ne pas simplement ajouter 1? (Math.random()+1).toString(36).substring(7);
emix
Parce que l'ajout de 1 ne résout aucun des deux problèmes abordés ici. Par exemple, (1) .toString (36) .substring (7) produit une chaîne vide.
amichair
L'utilisation Math.random().toString(36).substring(2,7)donne un résultat attendu qui ressemble plus à.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
C'est génial, mais lorsqu'il est exécuté dans Firefox avec N = 16, les ~ 6 derniers chiffres finissent par être zéro ... (Mais cela satisfait cependant le désir du PO pour 5 caractères aléatoires.)
Edward Newell
128

La solution la plus compacte, car sliceest plus courte que substring. La soustraction de la fin de la chaîne permet d'éviter le symbole à virgule flottante généré par la randomfonction:

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

ou même

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

Mise à jour: Ajout d'une approche supplémentaire à l'aide de la btoaméthode:

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
la source
Math.random().toString(36).slice(-5);- Et si Math.random()revient 0.0?
radiographie du
@ x-ray, vous obtiendrez "0";)
Valentin Podkamennyi
2
Exactement. ;) Et si Math.random()renvoie 0.5le résultat est "0.i". Je ne sais pas s'il y a d'autres cas de bord. Je voulais juste souligner que ce n'est pas une bonne réponse à la question (5 caractères de [a-zA-Z0-9]).
radiographie le
2
@ x-ray, je ne vais pas dire que c'est la bonne réponse, je dis juste qu'il s'agit d'une version compacte de la réponse @doubletap ci-dessus. J'utilise personnellement (+new Date + Math.random())pour éviter ce cas. Quoi qu'il en soit, merci pour la note.
Valentin Podkamennyi
1
Cette. Je ne sais pas pourquoi les autres réponses nécessitent autant de code
John Ktejik
100

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');
CaffGeek
la source
Une variante d'exemple ici peut être trouvée ici: mediacollege.com/internet/javascript/number/random.html
David
1
pourrait tout aussi bien décrémenter lendirectement dans une whileboucle
drzaus
Merci, je viens de poster ci-dessous une variante de cet exemple: stackoverflow.com/a/26682781/262379
Dinis Cruz
Si ceux-ci doivent être utilisés publiquement, vous devez probablement supprimer les voyelles. Un peu moins d'entropie, mais beaucoup plus sûr car vous ne pouvez pas générer de mots pouvant offenser les gens. C'est pourquoi j'aime ça, car je peux envoyer ma propre chaîne de caractères. Bon travail.
Nate Bunney
Assez hardcore, a fonctionné pour moi, merci!
Zaki Mohammed du
73

Une version plus récente avec l' opérateur de diffusion es6 :

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

  • Le 30nombre est arbitraire, vous pouvez choisir la longueur de jeton que vous souhaitez
  • Le 36est le numéro de radix maximum vous pouvez passer à numeric.toString () , ce qui signifie que tous les nombres et les lettres minuscules az
  • Le 2est utilisé pour choisir le 3ème index de la chaîne aléatoire qui ressemble à ceci:, "0.mfbiohx64i"nous pourrions prendre n'importe quel index après0.
Ou Duan
la source
Pourriez-vous expliquer? Surtout pourquoi vous passez 36 à toString () et pourquoi vous choisissez le 3ème élément?
vuza
5
c'est la meilleure solution
vainqueur
bien, mais cette solution n'inclut pas les caractères [AZ] comme question demandée, seulement [a-z0-9]
Nahuel Greco
72

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
la source
J'aime le mieux. Vous pouvez facilement modifier pour accepter des paramètres supplémentaires et ne renvoyer que des nombres, des diminutions ou des majuscules. Je ne pense pas que le style ultra-compressé soit nécessairewhile(s.length< L) s+= randomchar();
mastaBlasta
3
Le while(L--)fera également
vsync
1
Mieux vaut utiliser le plus robuste 'A'.charCodeAt(0)que le nombre magique 55(et de même pour le 61). D'autant plus que, sur ma plateforme en tout cas, le nombre magique qui revient est 65. Ce code se documentera également mieux.
Grumdrig
J'ai créé une variante optimisée pour la minification (46 octets de moins) de votre implémentation ici: stackoverflow.com/a/52412162
Waruyama
Bonne chance pour le débogage de @Waruyama. C'est à ça que sert le webpack!
Dylan Watson
61

Générateur de chaînes aléatoires (alpha-numérique | alpha | numérique)

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


Bien que ce qui précède utilise des vérifications supplémentaires pour la sortie A / N, A, N souhaitée , décomposons-la par l'essentiel (alpha-numérique uniquement) pour une meilleure compréhension:

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

Imaginons les plages de la table de caractères ASCII :

_____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 gamme de 0..61(ce dont nous avons besoin). Corrigeons
l'aléatoire 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' opération conditionnelle du tableau ci-dessus:

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

À partir de l'explication ci-dessus, voici l' extrait alpha-numérique résultant :

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"

Ou si vous voulez:

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
la source
33

La manière la 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. L'exemple de sortie est 4mtxjou 4mv90ou4mwp1

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

La manière la plus sûre est:

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

Cela générera une chaîne aléatoire de 4 ou 5 caractères, toujours différents. L'exemple de sortie est comme 30jzmou 1r591ou4su1a

Dans les deux cas, la première partie génère un nombre aléatoire. La .toString(36)pièce a converti le nombre en une représentation base36 (alphadécimale) de celui-ci.

MasqueradeCircus
la source
Je ne sais pas trop comment cela répond à la question; Il s'agit d'une question de 7 ans avec de nombreuses réponses valides déjà. Si vous choisissez de fournir une nouvelle réponse, vous devez vraiment prendre des précautions supplémentaires pour vous assurer que votre réponse est bien expliquée et documentée.
Claies
1
Si vous utilisez Date, pourquoi ne l'utilisez-vous pas comme:(+new Date).toString(36)
seniorpreacher
J'aime votre solution de nombres aléatoires mais 9e6 ne donne que 9 millions de possibilités sur les 60,4 millions pour 5 chiffres (36 ^ 5) afin que vous puissiez la remplacer par (0|Math.random()*6.04e7).toString(36)pour la couvrir.
Le Droid
1
Je voulais une chaîne aléatoire assez longue avec une routine aussi courte que possible (pour une démo de code) qui n'a pas besoin d'être étonnante sur le plan cryptographique, il suffit de produire un joli "fluff" visuel aléatoire. J'aime cette réponse la meilleure (votre 2e), alors merci. Mes deux cents: je peux le battre pour la brièveté avec une combinaison de touches moins, et il sera généralement produire 13 caractères aléatoires (sans période): (Math.random()*1e20).toString(36).
Andrew Willems
un scrupule que j'ai avec cette réponse est qu'elle n'utilisera pas [AZ] qui se trouve être dans la question d'origine.
user.friendly
22

Voici quelques doublures simples. Modifiez new Array(5)pour définir la longueur.

Comprenant 0-9a-z

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

Comprenant 0-9a-zA-Z

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

Je sais que tout le monde a déjà raison, mais j'avais envie d'essayer celui-ci de la manière la plus légère possible (lumière sur le code, pas sur le 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));

Cela prend un peu de temps pour envelopper votre tête, mais je pense que cela montre vraiment à quel point la syntaxe de javascript est géniale.

Roderick
la source
20
Si vous essayez de garder le code court, pourquoi écrire current = current ? current : '';quand vous pouvez écrire current = current || '';
CaffGeek
9
puisque nous parlons ici de micro-optimisation, je suggérerais en fait de sauter l'affectation de variable entièrement si ce n'est pas nécessaire:current || (current = '');
Thomas Heymann
Tenter une micro-optimisation tout en utilisant un algorithme récursif "agréable" mais gaspillant les ressources n'a aucun sens :-) Une boucle for est toujours meilleure en Javascript et bat la récursivité très longtemps, jusqu'à ce que de très grandes avancées dans le code d'optimisation des runtimes soient faites.
Mörre
17

Si vous utilisez Lodash ou Underscore , alors c'est si simple:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
vigne
la source
6
Lodash utilise_.sampleSize('asdfgh',5).join('')
marlo
2
En fait, ce n'est pas une bonne solution, car par document, chaque personnage provient d'un index unique. Cela signifie que ce n'est pas vraiment aléatoire, car aucun personnage ne peut / ne pourra jamais se répéter.
random_user_name
16

Pour répondre à l'exigence [a-zA-Z0-9] et à la longueur = 5, utilisez

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

Des lettres minuscules, des lettres majuscules et des chiffres apparaîtront.

Sergio Cabral
la source
1
Je suppose que Math.random () pourrait conduire à une chaîne de base64 avec trop peu de caractères.
Leif
14

Dans le cas où quelqu'un est intéressé par une ligne unique (bien que non formatée comme telle 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 5par la longueur de la chaîne souhaitée. Merci à @AriyaHidayat dans ce post pour la solution à la mapfonction ne fonctionnant pas sur le tableau clairsemé créé par Array(5).

Martijn de Milliano
la source
13
Chaque programme javascript est un "one-liner" si vous le formatez comme tel
hacklikecrack
13

Voici la méthode que j'ai créée.
Il créera une chaîne contenant à la fois des majuscules et des minuscules.
De plus, j'ai inclus la fonction qui créera également une chaîne alphanumérique.

Exemples pratiques:
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 à niveau juillet 2015
Cela fait la même chose mais est plus logique et inclut 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)));
}
Adam
la source
Avec cette fonction, vous ne pouvez jamais obtenir une lettre majuscule supérieure à «M» ou une lettre minuscule inférieure à «n».
erkanyildiz
Vraiment? ooh! le testera probablement plus alors. Hmm, cependant, étant donné que c'est une chaîne aléatoire et que nous ne nous soucions pas vraiment des lettres qu'il contient (tant qu'elles sont aléatoires), il fait toujours ce que nous voulons qu'il fasse, ce qui est tout ce qui compte, mais oui, il fournira un mise à niveau, merci.
Adam
12

En supposant que vous utilisez underscorejs, il est possible de générer élégamment une chaîne aléatoire en seulement deux lignes:

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
TIC Tac
la source
6
Cela fera que la valeur retournée aura tous les caractères uniques. De plus, la longueur de la chaîne est limitée à la longueur de var possible.
Yefu
10
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
Nahuel Greco
la source
Solution simple et propre
Mark Swardstrom
Cela mérite un plus grand +1
Walid Ammar
10

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

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;
}
yaroslav
la source
2
Excellente réponse, mais la probabilité n'est pas uniforme. Il y a 62 caractères possibles et crypto.getRandomValuesrenvoie l'une des 256 valeurs uniques. Parce que 256 n'est pas divisé par 62, vous finissez par avoir une probabilité légèrement plus élevée d'obtenir les caractères AH. Je pense que la meilleure solution est de faire ce que YouTube a fait, et d'ajouter simplement 2 caractères supplémentaires (éventuellement -et _) au jeu de caractères. Quoi qu'il en soit, excellent travail - cette réponse a besoin de beaucoup plus d'amour :)
TeWu
l'ajout - et _ est une excellente idée car il vous donnera l'ensemble complet de base64 sans danger pour les URL
cowbert
8

Le problème avec les réponses aux questions "J'ai besoin de chaînes aléatoires" (dans n'importe quelle langue) est que pratiquement chaque solution utilise une spécification primaire erronée de longueur de chaîne . Les questions elles-mêmes révèlent rarement pourquoi les chaînes aléatoires sont nécessaires, mais je vous mets au défi de rarement avoir besoin de chaînes aléatoires de longueur, disons 8. Ce dont vous avez invariablement besoin, c'est d'un certain nombre de chaînes uniques , par exemple, à utiliser comme identificateurs dans un certain but.

Il existe deux façons principales d'obtenir des chaînes strictement uniques : de manière déterministe (qui n'est pas aléatoire) et de stocker / comparer (ce qui est onéreux). Qu'est-ce qu'on fait? Nous abandonnons le fantôme. Nous optons plutôt pour l' unicité probabiliste . Autrement dit, nous acceptons qu'il existe un risque (aussi faible soit-il) que nos cordes ne soient pas uniques. C'est là que la compréhension de la probabilité de collision et de l' entropie est utile.

Je vais donc reformuler le besoin invariable comme nécessitant un certain nombre de chaînes avec un petit risque de répétition. À titre d'exemple concret, supposons que vous souhaitiez générer un potentiel de 5 millions d'ID. Vous ne voulez pas stocker et comparer chaque nouvelle chaîne et vous voulez qu'elles soient aléatoires, vous acceptez donc un risque de répétition. Par exemple, supposons un risque de moins de 1 sur mille milliards de chances de répétition. Alors, quelle longueur de chaîne avez-vous besoin? Eh bien, cette question est sous-spécifiée car elle dépend des caractères utilisés. Mais plus important encore, c'est erroné. Ce dont vous avez besoin est une spécification de l'entropie des cordes, pas de leur longueur. L'entropie peut être directement liée à la probabilité de répétition d'un certain nombre de chaînes. La longueur de chaîne ne peut pas.

Et c'est là qu'une bibliothèque comme EntropyString peut vous aider. Pour générer des ID aléatoires qui ont moins de 1 chance sur 1 000 milliards de répétitions dans 5 millions de chaînes en utilisant 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-stringutilise un jeu de caractères avec 32 caractères par défaut. Il existe d'autres jeux de caractères prédéfinis et vous pouvez également spécifier vos propres caractères. Par exemple, générer des ID avec la même entropie que ci-dessus mais en utilisant des caractères hexadécimaux:

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

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

const string = random.string(bits)

"27b33372ade513715481f"

Notez la différence de longueur de chaîne en raison de la différence du nombre total de caractères dans le jeu de caractères utilisé. Le risque de répétition dans le nombre spécifié de chaînes potentielles est le même. Les longueurs de chaîne ne le sont pas. Et surtout, le risque de répétition et le nombre potentiel de chaînes est explicite. Plus besoin de deviner avec la longueur de la chaîne.

ciel de dingo
la source
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('');
}

C'est aussi propre que possible. C'est aussi rapide, http://jsperf.com/ay-random-string .

Gajus
la source
Pour moi, cela génère toujours des chaînes aléatoires avec strLength - 1: - /
xanderiel
3
Passer de --strLengthà strLength--fixe pour moi.
xanderiel
7

Vous pouvez parcourir un tableau d'éléments et les ajouter récursivement à une variable de chaîne, par exemple si vous vouliez 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));

Andy
la source
6

Je n'ai pas trouvé de solution propre pour prendre en charge les caractères minuscules et majuscules.

Prise en charge des minuscules uniquement:

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

S'appuyant sur cette solution pour prendre en charge les minuscules et les majuscules:

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

Modifiez le 5dans substr(2, 5)pour ajuster à la longueur dont vous avez besoin.

ravishi
la source
6

Bon mot:

Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
Andrew
la source
Pour le raccourcir, remplacez l'argument par Array(15)une valeur plus petite. Par exemple: Array(4).
Andrew
J'adore vraiment cette solution, simple et claire. Il génère 15 nombres aléatoires entre 0 et 1, génère l'hexadécimal, puis supprime les deux premiers caractères. Enfin, il les fusionne tous.
Siscia
5

Cela fonctionne à coup sûr

<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
la source
5

Que diriez-vous de quelque chose comme ça: Date.now().toString(36) Pas très aléatoire, mais court et assez unique à chaque fois que vous l'appelez.

Swergas
la source
1
Malheureusement, ce ne sera pas unique, car Date.now()il n'a qu'une résolution en millisecondes. Lorsqu'il est exécuté dans une boucle simple, par exemple, vous obtiendrez de nombreux doublons. for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }.
Nate
5

Caractères alphanumériques insensibles à la casse:

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

L'avantage de cette fonction est que vous pouvez obtenir une chaîne aléatoire de longueur différente et qu'elle garantit la longueur de la chaîne.

Respecter la casse tous les caractères:

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

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

Caractères personnalisés

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
la source
Cette réponse convient mieux à mon cas d'utilisation. Ce serait cool si vous pouviez ajouter un var possiblelike dans la réponse acceptée, donc le résultat de la fonction est plus configurable.
Denis.Sabolotni
4

Générez une chaîne de 10 caractères. La longueur est définie par paramètre (10 par défaut).

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
la source
4

Vous pouvez utiliser coderain . C'est une bibliothèque pour générer des codes aléatoires selon un modèle donné. Utilisez #comme espace réservé pour les caractères majuscules et minuscules ainsi que pour les chiffres:

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

Il existe d'autres espaces réservés comme Apour les lettres majuscules ou 9pour les chiffres.

Ce qui peut être utile, c'est que l'appel .next()vous donnera toujours un résultat unique afin que vous n'ayez pas à vous soucier des doublons.

Voici une application de démonstration qui génère une liste de codes aléatoires uniques .

Divulgation complète: je suis l'auteur de coderain.

Lukasz Wiktor
la source
NON NON NON - utilisez des méthodes natives.