2797 votes

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 pris au hasard dans l'ensemble [a-zA-Z0-9] .

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

87 votes

Avertissement : Aucune des réponses n'a de true-random résultat ! Ils ne sont que pseudo-random . Lorsque vous utilisez des chaînes aléatoires pour la protection ou la sécurité, n'en utilisez aucune ! !! Essayez l'une de ces api : random.org

56 votes

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

20 votes

Veuillez mettre la solution dans une solution.

3681voto

csharptest.net Points 16556

Je pense que ça va marcher pour vous :

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

console.log(makeid(5));

144 votes

Cela convient pour les chaînes courtes, mais attention, l'utilisation de l'option += sur des chaînes de caractères comme celle-ci lui donne un comportement O(n^2). Si vous voulez créer des chaînes de caractères plus longues, vous devriez créer un tableau de caractères individuels et les réunir à la fin.

126 votes

@dan_waterworth Ça n'a probablement pas d'importance dans presque tout cas : codinghorror.com/blog/2009/01/

5 votes

Ça peut sembler faux, mais floor est inutile : for(var text='' ; text.length < 5 ;) text += possible.charAt(Math.random() * possible.length)

3154voto

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

Note : L'algorithme ci-dessus présente les faiblesses suivantes :

  • Il générera entre 0 et 6 caractères, car les zéros de fin de chaîne sont supprimés lors de la mise en 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 l'article "Comment imprimer avec précision des nombres à virgule flottante" .)
  • Math.random() peut produire une sortie prévisible ("d'apparence aléatoire" mais pas vraiment aléatoire) selon l'implémentation. La chaîne qui en résulte 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 de caractères, en raison de l'effet d'entraînement. paradoxe de l'anniversaire . (sqrt(36^6) = 46656)

17 votes

J'aime ça, mais il a besoin de [a-zA-Z].

331 votes

Math.random().toString(36).substr(2, 5) parce que .substring(7) fait en sorte qu'il soit plus long que 5 caractères. Des points, quand même !

1 votes

Et une version compatible avec ActionScript 2 : Math.round(Math.random()*Math.pow(36,5)).toString(36)

190voto

amichair Points 1149

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 la chaîne N à 16 caractères. La solution suivante 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 et 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 l'intervalle [0,1], c'est-à-dire entre 0 (inclusif) et 1 (exclusif).
  2. Convertir le nombre en une chaîne de caractères en base 36, c'est-à-dire en utilisant les caractères 0-9 et a-z.
  3. Remplir de zéros (résout le premier problème).
  4. Supprimez le préfixe '0.' et les zéros de remplissage supplémentaires.
  5. Répétez la chaîne suffisamment de fois pour qu'elle contienne au moins N caractères (en joignant des chaînes vides avec la chaîne aléatoire la plus courte utilisée comme délimiteur).
  6. Découpe exactement N caractères de la chaîne.

Autres réflexions :

  • 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 maximale de la chaîne à N = 16 dans la réponse originale est mesurée en Chrome. Dans Firefox, elle est de N = 11. Mais comme nous l'avons expliqué, la deuxième solution consiste à prendre en charge toute longueur de chaîne demandée, et non à ajouter du caractère aléatoire, ce qui ne fait pas une grande différence.
  • Toutes les chaînes de caractères renvoyées ont une probabilité égale d'être renvoyées, du moins dans la mesure où les résultats renvoyés par Math.random() sont distribués de manière égale (il ne s'agit pas d'un caractère aléatoire de force cryptographique, dans tous les 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 c'est également vrai dans la réponse originale, puisque lors de la conversion en base 36, les derniers bits peuvent ne pas faire partie des bits aléatoires originaux. 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 distribué uniformément. Encore une fois, dans la plupart des cas, cela n'a pas d'importance, mais nous découpons la chaîne finale à partir 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 répliques de style fonctionnel que j'ai trouvé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 originale qui demandait des lettres majuscules et minuscules).
  • Toutes les chaînes de longueur N ont une probabilité égale d'être retournées (c'est-à-dire que les chaînes ne contiennent pas de répétitions).
  • Ils sont basés sur une fonction map, plutôt que sur l'astuce toString(36), ce qui les rend plus directs et faciles à comprendre.

Donc, disons que votre alphabet de choix est

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Les deux sont donc équivalentes, et vous pouvez choisir celle qui vous semble la plus intuitive :

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

Edit :

J'ai l'impression que qubyte et Martijn de Milliano a proposé des solutions similaires à la dernière (bravo !), ce qui m'a échappé. Comme elles n'ont pas l'air aussi courtes au premier coup d'œil, je vais quand même les laisser ici au cas où quelqu'un voudrait vraiment une solution en une phrase :-)

J'ai également remplacé "new Array" par "Array" dans toutes les solutions pour gagner quelques octets supplémentaires.

0 votes

Pourquoi ne pas simplement ajouter 1 ? (Math.random()+1).toString(36).substring(7);

0 votes

Parce qu'ajouter 1 ne résout aucun des deux problèmes discutés ici. Par exemple, (1).toString(36).substring(7) produit une chaîne vide.

0 votes

Utilisation de Math.random().toString(36).substring(2,7) donne un résultat attendu qui ressemble davantage au .substring(2, n+2)

119voto

CaffGeek Points 10925

Quelque chose comme ceci 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');

0 votes

Une variante de cet exemple peut être trouvée ici : mediacollege.com/internet/javascript/number/random.html

2 votes

On pourrait tout aussi bien décrémenter len directement dans un while boucle

0 votes

Merci, je viens de poster ci-dessous une variante coffeescript de cet exemple : stackoverflow.com/a/26682781/262379

78voto

kennebec Points 33886
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));

0 votes

C'est celle que je préfère. Vous pourriez facilement le modifier pour qu'il accepte des paramètres supplémentaires et qu'il ne renvoie que des nombres, des minima ou des maxima. Je ne pense pas que le style ultra-compressé soit nécessaire. while(s.length< L) s+= randomchar();

3 votes

Aussi while(L--) le fera

3 votes

Il est préférable d'utiliser le plus robuste 'A'.charCodeAt(0) plutôt 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 s'auto-documentera mieux aussi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X