Generar cadenas / caracteres aleatorios en JavaScript

1781

Quiero una cadena de 5 caracteres compuesta de caracteres elegidos al azar del conjunto [a-zA-Z0-9].

¿Cuál es la mejor manera de hacer esto con JavaScript?

Tom Lehman
fuente
48
Advertencia: ¡Ninguna de las respuestas tiene true-randomresultado! Son solamente pseudo-random. Cuando use cadenas aleatorias para protección o seguridad, ¡no use ninguna de ellas! Pruebe una de estas aplicaciones: random.org
Ron van der Heijden
48
Math.random (). ToString (36) .replace (/ [^ az] + / g, '')
Muaz Khan
13
Por favor ponga la solución en una solución.
chryss
216
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
Friedrich
12
Nota La API de aleatoriedad de cripto web HTML5 proporciona aleatoriedad real.
mikemaccana

Respuestas:

2433

Creo que esto funcionará para ti:

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
fuente
117
Esto está bien para cadenas cortas, pero tenga cuidado, usar +=cadenas como esta hace que tenga un comportamiento O (n ^ 2). Si desea crear cadenas más largas, debe crear una matriz de caracteres individuales y unirlos al final.
dan_waterworth
97
@dan_waterworth Probablemente no importe en casi ningún caso: codinghorror.com/blog/2009/01/…
Alex Reece
77
@dan_waterworth, en realidad, a +=menudo es más rápido por alguna razón, incluso se usa dentro de bucles - jsperf.com/join-vs-concatenation
Konrad Borowski
18
@ JonathanPaulson Muéstrame los números . Vea el comentario anterior con un enlace jsperf o jsperf.com/sad-tragedy-of-microoptimization o sitepen.com/blog/2008/05/09/string-performance-an-analysis, etc. Además, esta pregunta involucra solo 5 concatenaciones .
Alex Reece
11
@codenamejames Por favor , no use esto en su contraseña de salazón. Es solo pseudoaleatorio, no seguro. Suponiendo que está usando Node (ni siquiera estoy seguro de por dónde empezar si está usando sal del lado del cliente), use cryptoen su lugar.
Hidrotermal
2330

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

Nota: El algoritmo anterior tiene las siguientes debilidades:

  • Generará entre 0 y 6 caracteres debido al hecho de que los ceros finales se eliminan al encadenar puntos flotantes.
  • Depende profundamente del algoritmo utilizado para stringificar números de coma flotante, lo cual es terriblemente complejo. (Consulte el documento "Cómo imprimir con precisión números de coma flotante" ).
  • Math.random()puede producir resultados predecibles ("aleatorios" pero no realmente aleatorios) dependiendo de la implementación. La cadena resultante no es adecuada cuando necesita garantizar unicidad o imprevisibilidad.
  • Incluso si produjo 6 caracteres impredecibles y aleatorios uniformes, puede esperar ver un duplicado después de generar solo alrededor de 50,000 cadenas, debido a la paradoja del cumpleaños . (sqrt (36 ^ 6) = 46656)
doble toque
fuente
276
Math.random().toString(36).substr(2, 5), porque .substring(7)hace que tenga más de 5 caracteres. Puntos completos, todavía!
dragón
81
@Scoop El toStringmétodo de un tipo de número en javascript toma un parámetro opcional para convertir el número en una base dada. Si pasa dos, por ejemplo, verá su número representado en binario. Similar al hexadecimal (base 16), la base 36 usa letras para representar dígitos más allá de 9. Al convertir un número aleatorio a la base 36, terminarás con un montón de letras y números aparentemente aleatorios.
Chris Baker
76
¡Se ve hermoso pero en algunos casos esto genera una cadena vacía! Si random devuelve 0, 0.5, 0.25, 0.125 ... resultará en una cadena vacía o corta.
gertas
68
@gertas Esto puede evitarse por(Math.random() + 1).toString(36).substring(7);
George Reith
84
Guy, esto es prácticamente inútil. Ejecútelo solo 1000000 veces y generalmente obtendrá alrededor de 110000 repeticiones: valores var = {}, i = 0, duplicateCount = 0, val; while (i <1000000) {val = Math.random (). toString (36) .substring (7); if (valores [val]) {duplicateCount ++; } valores [val] = 1; i ++; } console.log ("DUPLICADOS TOTALES", duplicateCount);
hacklikecrack 01 de
463

Math.random es malo para este tipo de cosas

Opción 1

Si puede hacer este lado del servidor , simplemente use el módulo de cifrado :

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

// "bb5dc8842ca31d4603d6aa11448d1654"

La cadena resultante tendrá el doble de longitud que los bytes aleatorios que genere; cada byte codificado en hexadecimal tiene 2 caracteres. 20 bytes serán 40 caracteres de hexadecimal.


opcion 2

Si tienes que hacer esto cliente , quizás pruebe el módulo uuid:

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

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

Opción 3

Si tiene que hacer este lado del cliente y no tiene que admitir navegadores antiguos, puede hacerlo sin dependencias:

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


Para más información sobre crypto.getRandomValues -

El crypto.getRandomValues()método le permite obtener valores aleatorios criptográficamente fuertes. El conjunto dado como parámetro está lleno de números aleatorios (aleatorio en su significado criptográfico).

Aquí hay un pequeño ejemplo de consola:

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

Para el soporte de IE11 puede usar:

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

Para la cobertura del navegador, consulte https://caniuse.com/#feat=getrandomvalues

Gracias
fuente
44
Exactamente. Si bien un UUID está bien para asignar una ID a una cosa, usarlo como una cadena de caracteres aleatorios no es una gran idea por esta (y probablemente otras) razones.
wmassingham
2
No es necesario .map()en la opción 3. Array.from(arr, dec2hex).join('')=== Array.from(arr).map(dec2hex).join(''). Gracias por presentarme estas características :-)
Fred Gandt
66
Debería mencionar en la respuesta que la opción 2 también necesita node.js para funcionar, no es javascript puro.
Esko
55
Si bien es más seguro criptográficamente, en realidad esto no satisface los requisitos de la pregunta porque solo genera 0-9 y af (hexadecimal), y no 0-9, az, AZ.
qJake
1
¿No se requirepuede usar el módulo solo en el lado del servidor?
aJetHorn
173

Corto, fácil y confiable.

Devuelve exactamente 5 caracteres aleatorios, a diferencia de algunas de las respuestas mejor calificadas que se encuentran aquí.

Math.random().toString(36).substr(2, 5);
Anillo de plata
fuente
99
¿Qué pasa si Math.random().toString(36)devuelve un número con menos de 5 caracteres?
Michael Litvin
3
Bueno, esa es una acusación interesante de @ Aperçu, no estoy diciendo que inventé la solución, pero la he estado usando en mis proyectos durante años. Y no tiene nada que ver con el comentario que mencionaste. Y estoy bastante seguro de que en SO lo que importa es la información más útil en el lugar correcto e incluso si ya existe en otro lugar también. Afortunadamente, parece que al menos 51 hombres han encontrado útil esta respuesta, ¡de nada!
Silver Ringvee
3
Para evitar obtener una cadena vacía en caso de Math.random () devuelve 0, puede usarfunction getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
mikep
55
@rinogo Math.random () puede devolver 0 pero no 1 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
mikep
66
Ejecuté este código 1,000,000,000 de veces y aún no obtuve una cadena vacía: jsfiddle.net/mtp5730r Diría que estás bastante a salvo de obtener una cadena vacía.
MacroMan
157

Aquí hay una mejora en la excelente respuesta de doubletap . El original tiene dos inconvenientes que se abordan aquí:

Primero, como otros han mencionado, tiene una pequeña probabilidad de producir cadenas cortas o incluso una cadena vacía (si el número aleatorio es 0), lo que puede romper su aplicación. Aquí hay una solución:

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

En segundo lugar, tanto el original como la solución anterior limitan el tamaño de la cadena N a 16 caracteres. Lo siguiente devolverá una cadena de tamaño N para cualquier N (pero tenga en cuenta que el uso de N> 16 no aumentará la aleatoriedad ni disminuirá la probabilidad de colisiones):

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

Explicación:

  1. Elija un número aleatorio en el rango [0,1), es decir, entre 0 (inclusive) y 1 (exclusivo).
  2. Convierta el número en una cadena de base 36, es decir, utilizando los caracteres 0-9 y az.
  3. Pad con ceros (resuelve el primer problema).
  4. Corta el '0' principal prefijo y ceros de relleno extra.
  5. Repita la cadena suficientes veces para tener al menos N caracteres (uniendo cadenas vacías con la cadena aleatoria más corta utilizada como delimitador).
  6. Corte exactamente N caracteres de la cadena.

Pensamientos adicionales:

  • Esta solución no utiliza letras mayúsculas, pero en casi todos los casos (sin juego de palabras) no importa.
  • La longitud máxima de la cadena en N = 16 en la respuesta original se mide en Chrome. En Firefox es N = 11. Pero como se explicó, la segunda solución se trata de admitir cualquier longitud de cadena solicitada, no se trata de agregar aleatoriedad, por lo que no hace mucha diferencia.
  • Todas las cadenas devueltas tienen la misma probabilidad de ser devueltas, al menos en la medida en que los resultados devueltos por Math.random () se distribuyan uniformemente (esto no es aleatoriedad de fuerza criptográfica, en cualquier caso).
  • No se pueden devolver todas las cadenas posibles de tamaño N. En la segunda solución esto es obvio (ya que la cadena más pequeña simplemente se está duplicando), pero también en la respuesta original esto es cierto ya que en la conversión a base-36 los últimos pocos bits pueden no ser parte de los bits aleatorios originales. Específicamente, si observa el resultado de Math.random (). ToString (36), notará que el último carácter no está distribuido de manera uniforme. Nuevamente, en casi todos los casos no importa, pero cortamos la cadena final desde el principio en lugar del final de la cadena aleatoria para que las cadenas cortas (por ejemplo, N = 1) no se vean afectadas.

Actualizar:

Aquí hay un par de otras frases de estilo funcional que se me ocurrieron. Se diferencian de la solución anterior en que:

  • Utilizan un alfabeto arbitrario explícito (más genérico y adecuado para la pregunta original que pedía letras mayúsculas y minúsculas).
  • Todas las cadenas de longitud N tienen la misma probabilidad de ser devueltas (es decir, las cadenas no contienen repeticiones).
  • Se basan en una función de mapa, en lugar del truco toString (36), que los hace más directos y fáciles de entender.

Entonces, digamos que tu alfabeto de elección es

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Entonces estos dos son equivalentes entre sí, por lo que puede elegir el que sea más intuitivo para usted:

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

y

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

Editar:

Parece que qubyte y Martijn de Milliano idearon soluciones similares a esta última (¡felicitaciones!), Que de alguna manera me perdí. Como no se ven tan cortos de un vistazo, lo dejaré aquí de todos modos en caso de que alguien realmente quiera una frase :-)

Además, se reemplazó 'nueva matriz' por 'matriz' en todas las soluciones para eliminar algunos bytes más.

amichair
fuente
¿Por qué no solo agregar 1? (Math.random()+1).toString(36).substring(7);
emix
Porque agregar 1 no resuelve ninguno de los dos problemas discutidos aquí. Por ejemplo, (1) .toString (36) .substring (7) produce una cadena vacía.
amichair
El uso Math.random().toString(36).substring(2,7)da un resultado esperado que es más como el.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
Esto es genial, pero cuando se ejecuta en Firefox con N = 16, los últimos ~ 6 dígitos terminan en cero ... (Pero satisface el deseo del OP de 5 caracteres aleatorios).
Edward Newell
128

La solución más compacta, porque slicees más corta que substring. Restar del final de la cadena permite evitar el símbolo de coma flotante generado por la randomfunción:

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

o incluso

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

Actualización: Se agregó un enfoque más usando el btoamétodo:

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
fuente
Math.random().toString(36).slice(-5);- ¿Y si Math.random()vuelve 0.0?
rayos X
@ rayos X, obtendrá "0";)
Valentin Podkamennyi
2
Exactamente. ;) Y si Math.random()devuelve 0.5el resultado es "0.i". No estoy seguro si hay otros casos límite. Solo quería señalar que esta no es una respuesta correcta a la pregunta (5 caracteres de [a-zA-Z0-9]).
rayos X
2
@ rayos X, no voy a decir que esta es la respuesta correcta, solo digo que esta es una versión compacta de la respuesta @doubletap anterior. Yo personalmente uso (+new Date + Math.random())para prevenir este caso. De todos modos, gracias por la nota.
Valentin Podkamennyi
1
Esta. No sé por qué otras respuestas requieren tanto código
john ktejik
100

Algo como esto debería funcionar

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

Llame con el juego de caracteres predeterminado [a-zA-Z0-9] o envíe el suyo:

var randomValue = randomString(5);

var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');
CaffGeek
fuente
Aquí puede encontrar una variante de ejemplo aquí: mediacollege.com/internet/javascript/number/random.html
David
1
también podría disminuir lendirectamente en un whilebucle
drzaus
Gracias, acabo de publicar a continuación una variación de coffeescript de este ejemplo: stackoverflow.com/a/26682781/262379
Dinis Cruz
Si se van a usar públicamente, entonces probablemente deberías eliminar las vocales. Un poco menos de entropía, pero mucho más seguro ya que no puede generar palabras que puedan ofender a las personas. Por eso me gusta esto, ya que puedo enviar mi propia cadena de caracteres. Buen trabajo.
Nate Bunney
Bastante hardcore, funcionó para mí, ¡Gracias!
Zaki Mohammed
73

Una versión más nueva con es6 spread operator :

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

  • los 30 es un número arbitrario, puede elegir la longitud de token que desee
  • El 36es el número máximo de radix que puede pasar a numeric.toString () , lo que significa todos los números y letras minúsculas az
  • Se 2utiliza para seleccionar el 3er índice de la cadena aleatoria que se ve así: "0.mfbiohx64i"podríamos tomar cualquier índice después0.
O Duan
fuente
¿Podrías explicar? ¿Especialmente por qué pasa 36 a toString () y por qué elige el tercer elemento?
vuza
55
esta es la mejor solución
vencedor el
bueno, pero esta solución no incluye caracteres [AZ] como pregunta solicitada, solo [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
fuente
Me gusta esto lo mejor. Puede modificar fácilmente para aceptar parámetros adicionales y devolver solo números, reducciones o límites. No creo que el estilo ultra comprimido sea necesariowhile(s.length< L) s+= randomchar();
mastaBlasta
3
También while(L--)lo hará
vsync
1
Es mejor usar el número más robusto 'A'.charCodeAt(0)que el mágico 55(y lo mismo para el 61). Particularmente desde entonces, en mi plataforma, el número mágico que regresa es 65. Ese código también se documentará mejor.
Grumdrig
Creé una
Buena suerte siempre depurando que @Waruyama. ¡Para eso está el webpack!
Dylan Watson
61

Generador de cadenas aleatorias (alfanumérico | alfa | numérico)

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


Si bien lo anterior utiliza verificaciones adicionales para la salida de A / N, A, N deseada , vamos a desglosar lo esencial (solo alfanumérico) para una mejor comprensión:

  • Cree una función que acepte un argumento (longitud deseada del resultado de cadena aleatorio)
  • Crea una cadena vacía como var str = ""; para concatenar caracteres aleatorios
  • Dentro de un bucle, cree un randnúmero de índice del 0 al 61 (0..9 + A..Z + a..z = 62)
  • Cree una lógica condicional para Ajustar / arreglarrand (ya que es 0..61) incrementándola en algún número (vea los ejemplos a continuación) para volver a la derechaCharCode número y el Carácter relacionado.
  • Dentro del bucle se concatena a strunString.fromCharCode( incremented rand )

Imaginemos los rangos de la tabla de caracteres 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 )da un rango de 0..61(lo que necesitamos). Arreglemos
el azar para obtener los rangos correctos de charCode :

      |   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 lógica de operación condicional de la tabla anterior:

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

De la explicación anterior, aquí está el fragmento alfanumérico resultante :

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"

O si vas a:

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

La forma más simple es:

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

Esto genera cadenas aleatorias de 5 caracteres en función de la hora actual. Ejemplo de salida es 4mtxjo 4mv90o4mwp1

El problema con esto es que si lo llamas dos veces en el mismo segundo, generará la misma cadena.

La forma más segura es:

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

Esto generará una cadena aleatoria de 4 o 5 caracteres, siempre diferente. Ejemplo de salida es como 30jzmo 1r591o4su1a

En ambos sentidos, la primera parte genera un número aleatorio. La .toString(36)parte arroja el número a una representación base36 (alfadecimal) del mismo.

MascaradaCirco
fuente
No estoy muy seguro de cómo responde esto a la pregunta; Esta es una pregunta de 7 años con muchas respuestas válidas ya. Si elige proporcionar una nueva respuesta, debe tener mucho cuidado para asegurarse de que su respuesta esté bien explicada y documentada.
Claies
1
Si utiliza la fecha, ¿por qué no sólo lo utilizan como:(+new Date).toString(36)
seniorpreacher
Me gusta su solución de números aleatorios, pero 9e6 ofrece solo 9 millones de posibilidades sobre los 60.4 millones para 5 dígitos (36 ^ 5), por lo que podría reemplazarlo (0|Math.random()*6.04e7).toString(36)para cubrirlo.
Le Droid el
1
Quería una cadena aleatoria más larga con una rutina lo más corta posible (para una demostración de código) que no necesita ser criptográficamente asombrosa, solo produce una buena "pelusa" visual aleatoria. Me gusta esta respuesta la mejor (la segunda), así que gracias. Mis dos centavos: Me pueden superar, por dificultad con uno menos pulsaciones de teclas, y que por lo general se producen 13 caracteres aleatorios (sin punto): (Math.random()*1e20).toString(36).
Andrew Willems
Una duda que tengo con esta respuesta es que no usará [AZ], que está en la pregunta original.
user.friendly
22

Aquí hay algunos liners fáciles. Cambiar new Array(5)para establecer la longitud.

Incluso 0-9a-z

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

Incluso 0-9a-zA-Z

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

Sé que todos lo han entendido bien, pero sentí que quería probarlo de la manera más liviana posible (código ligero, no 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));

Toma un poco de tiempo entenderlo, pero creo que realmente muestra cuán increíble es la sintaxis de JavaScript.

Roderick
fuente
20
Si está tratando de mantener el código corto, ¿por qué escribir current = current ? current : '';cuando puede escribir current = current || ''?
CaffGeek
99
ya que estamos hablando de micro optimización aquí, en realidad sugeriría omitir la asignación de variables por completo si no es necesario:current || (current = '');
Thomas Heymann
Intentar la micro optimización mientras se usa un algoritmo recursivo "agradable" pero que desperdicia recursos no tiene sentido :-) Un bucle for todavía es mejor en Javascript y supera la recursividad a lo grande, hasta que se realicen grandes avances en el código de optimización de los tiempos de ejecución.
Mörre
17

Si está usando Lodash o Underscore , entonces es muy simple:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
viña
fuente
66
Lodash usa_.sampleSize('asdfgh',5).join('')
marlo
2
En realidad, esta no es una buena solución, porque por documentos cada carácter es de un índice único. Eso significa que no es realmente aleatorio, ya que ningún personaje puede / alguna vez se repetirá.
random_user_name
16

Para cumplir con el requisito [a-zA-Z0-9] y longitud = 5 use

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

Ocurrirán letras minúsculas, mayúsculas y números.

Sergio Cabral
fuente
1
Supongo que Math.random () podría conducir a una cadena base64 con muy pocos caracteres.
Leif
14

En caso de que alguien esté interesado en una línea (aunque no esté formateada como tal para su conveniencia) que asigne la memoria de una vez (pero tenga en cuenta que para cadenas pequeñas realmente no importa), aquí le mostramos cómo hacerlo:

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

Puede reemplazar 5por la longitud de la cadena que desee. Gracias a @AriyaHidayat en esta publicación por la solución a la mapfunción que no funciona en la matriz dispersa creada por Array(5).

Martijn de Milliano
fuente
13
Cada programa javascript es un 'one-liner' si lo formatea como tal
hacklikecrack
13

Aquí está el método que creé.
Creará una cadena que contiene caracteres en mayúsculas y minúsculas.
Además, he incluido la función que creará una cadena alfanumérica también.

Ejemplos de trabajo:
http://jsfiddle.net/greatbigmassive/vhsxs/ (solo alfa)
http://jsfiddle.net/greatbigmassive/PJwg8/ (alfanumérico)

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

Actualización de julio de 2015
Esto hace lo mismo pero tiene más sentido e incluye todas las letras.

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)));
}
Adán
fuente
Con esta función, nunca puede obtener una letra mayúscula mayor que 'M' o una letra minúscula menor que 'n'.
erkanyildiz
De Verdad? ¡Oh! probablemente lo probará más entonces. Hmm, sin embargo, dado que es una cadena aleatoria y realmente no nos importa qué letras hay en ella (siempre que sean aleatorias), entonces sigue haciendo lo que queremos que haga, que es todo lo que importa, pero sí, proporcionará un actualizar, gracias.
Adam
12

Suponiendo que use underscorejs , es posible generar cadenas aleatorias con elegancia en solo dos líneas:

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
tiktak
fuente
66
Esto hará que el valor devuelto tenga todos los caracteres únicos. Además, la longitud de la cadena está limitada a la longitud de var posible.
Yefu
10
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
Nahuel Greco
fuente
Solución simple y limpia
Mark Swardstrom
Esto merece un +1 más grande
Walid Ammar
10

Algoritmo rápido y mejorado. No garantiza el uniforme (ver comentarios).

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
fuente
2
Gran respuesta, pero la probabilidad no es uniforme. Hay 62 caracteres posibles y crypto.getRandomValuesdevuelve uno de los 256 valores únicos. Debido a que 256 no está dividido por 62, terminas teniendo una probabilidad ligeramente mayor de obtener caracteres AH. Creo que la mejor solución es hacer lo que hizo YouTube, y simplemente agregar 2 caracteres adicionales (posiblemente -y _) al conjunto de caracteres. De todos modos, gran trabajo: esta respuesta necesita mucho más amor :)
TeWu
agregar - y _ es una gran idea ya que le dará el conjunto completo base64 seguro de URL
cowbert
8

El problema con las respuestas a las preguntas "Necesito cadenas aleatorias" (en cualquier idioma) es que prácticamente todas las soluciones utilizan una especificación primaria defectuosa de longitud de cadena . Las preguntas en sí rara vez revelan por qué se necesitan las cadenas aleatorias, pero yo desafiaría que rara vez necesite cadenas aleatorias de longitud, digamos 8. Lo que necesita invariablemente es cierto número de cadenas únicas. , por ejemplo, para usarlas como identificadores para algún propósito.

Hay dos formas principales de obtener cadenas estrictamente únicas : determinista (que no es aleatorio) y almacenar / comparar (que es oneroso). qué hacemos? Renunciamos al fantasma. Vamos con unicidad probabilística en su lugar. Es decir, aceptamos que existe un riesgo (aunque pequeño) de que nuestras cadenas no sean únicas. Aquí es donde entender la probabilidad de colisión y la entropía es útil .

Así que reformularé la necesidad invariable de necesitar cierto número de cadenas con un pequeño riesgo de repetición. Como ejemplo concreto, supongamos que desea generar un potencial de 5 millones de ID. No desea almacenar y comparar cada nueva cadena, y desea que sean aleatorias, por lo que acepta cierto riesgo de repetición. Como ejemplo, supongamos un riesgo de menos de 1 en un billón de posibilidades de repetición. Entonces, ¿qué longitud de cuerda necesitas? Bueno, esa pregunta no está especificada, ya que depende de los caracteres utilizados. Pero lo más importante, es equivocado. Lo que necesita es una especificación de la entropía de las cadenas, no su longitud. La entropía puede estar directamente relacionada con la probabilidad de una repetición en cierto número de cadenas. La longitud de la cuerda no puede.

Y aquí es donde una biblioteca como EntropyString puede ayudar. Para generar ID aleatorios que tengan menos de 1 en un billón de posibilidades de repetirse en 5 millones de cadenas usando 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-stringutiliza un conjunto de caracteres con 32 caracteres de forma predeterminada. Existen otros conjuntos de caracteres predefinidos, y también puede especificar sus propios caracteres. Por ejemplo, generar ID con la misma entropía que la anterior pero utilizando caracteres hexadecimales:

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

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

const string = random.string(bits)

"27b33372ade513715481f"

Tenga en cuenta la diferencia en la longitud de la cadena debido a la diferencia en el número total de caracteres en el conjunto de caracteres utilizado. El riesgo de repetición en el número especificado de cadenas potenciales es el mismo. Las longitudes de cadena no son. Y lo mejor de todo, el riesgo de repetición y el número potencial de cadenas es explícito. No más adivinanzas con la longitud de la cuerda.

cielo de dingo
fuente
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('');
}

Esto es lo más limpio posible. También es rápido, http://jsperf.com/ay-random-string .

Gajus
fuente
Para mí, esto siempre genera cadenas aleatorias con strLength - 1: - /
xanderiel
3
Cambiar de --strLengtha strLength--me lo arregla.
xanderiel
7

Puede recorrer una matriz de elementos y agregarlos recursivamente a una variable de cadena, por ejemplo, si desea una secuencia de ADN aleatoria:

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

No encontré una solución limpia para admitir caracteres en minúsculas y mayúsculas.

Solo soporte en minúsculas:

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

Sobre la base de esa solución para admitir minúsculas y mayúsculas:

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

Cambie el 5de substr(2, 5)adaptarse a la longitud necesaria.

ravishi
fuente
6

Un trazador de líneas:

Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
Andrés
fuente
Para hacerlo más corto, cambie el argumento Array(15)a un valor menor. Por ejemplo: Array(4).
Andrew
Realmente amo esta solución, simple y clara. Genera 15 números aleatorios entre 0 y 1, genera el hexadecimal y luego elimina los dos primeros caracteres. Finalmente los está fusionando a todos juntos.
Siscia
5

Esto funciona seguro

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

¿Qué tal algo como esto ?: Date.now().toString(36) No muy aleatorio, pero corto y bastante único cada vez que lo llamas.

Swergas
fuente
1
Lamentablemente, esto no será único, ya que Date.now()solo tiene una resolución de milisegundos. Cuando se ejecuta en un bucle simple, por ejemplo, obtendrá muchos duplicados. for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }.
Nate
5

Caracteres alfanuméricos insensibles al caso:

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

El beneficio de esta función es que puede obtener una cadena aleatoria de diferente longitud y garantiza la longitud de la cadena.

Mayúsculas y minúsculas todos los caracteres:

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

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

Caracteres personalizados

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
fuente
Esta respuesta se ajusta más a mi caso de uso. Sería genial si pudiera agregar un me var possiblegusta en la respuesta aceptada, por lo que el resultado de la función es más configurable.
Denis.Sabolotni
4

Genera una cadena larga de 10 caracteres. La longitud se establece por parámetro (por defecto 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
fuente
4

Puedes usar coderain . Es una biblioteca para generar códigos aleatorios según el patrón dado. Úselo #como marcador de posición para caracteres en mayúsculas y minúsculas, así como dígitos:

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

Hay otros marcadores de posición como Aletras mayúsculas o 9dígitos.

Lo que puede ser útil es ese llamado .next() siempre le darán un resultado único para que no tenga que preocuparse por los duplicados.

Aquí hay una aplicación de demostración que genera una lista de códigos aleatorios únicos .

Divulgación completa: soy el autor de coderain.

Lukasz Wiktor
fuente
NO NO NO - use métodos nativos.