Genere cadenas / caracteres aleatorios en JavaScript

2250

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

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

13
  • 66
    Advertencia: ¡Ninguna de las respuestas da true-randomresultado! Ellos son los únicos pseudo-random. Cuando use cadenas aleatorias para protección o seguridad, ¡no use ninguna de ellas! Pruebe una de estas api: random.orgRon van der Heijden 29 de mayo de 2013 a las 11:33
  • 59
    Math.random (). ToString (36) .replace (/ [^ az] + / g, '')Muaz Khan 14 de septiembre de 2013 a las 14:47
  • 21
    Pon la solución en una solución. chryss 24 de septiembre de 2013 a las 4:36
  • 278
    Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);Friedrich 15/08/2014 a las 9:28
  • 15
    Nota La API de aleatoriedad de cifrado web HTML5 proporciona aleatoriedad real. mikemaccana 9 de enero de 2016 a las 16:54
3052

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

//Can change 7 to 2 for longer results.
let r = (Math.random() + 1).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 en gran medida del algoritmo utilizado para clasificar los números de punto flotante, que es horriblemente complejo. (Consulte el documento "Cómo imprimir números de punto flotante con precisión" ).
  • Math.random()puede producir una salida predecible ("de apariencia aleatoria" pero no realmente aleatoria) dependiendo de la implementación. La cadena resultante no es adecuada cuando necesita garantizar la singularidad o la imprevisibilidad.
  • Incluso si produjo 6 caracteres impredecibles y uniformemente aleatorios, puede esperar ver un duplicado después de generar solo alrededor de 50,000 cadenas, debido a la paradoja del cumpleaños . (raíz cuadrada de (36 ^ 6) = 46656)
22
  • 306
    Math.random().toString(36).substr(2, 5), porque .substring(7)hace que tenga más de 5 caracteres. ¡Puntos completos, todavía! dragon 7 de mayo de 2012 a las 8:13
  • 84
    @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 determinada. 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á del 9. Al convertir un número aleatorio en base 36, terminará con un montón de letras y números aparentemente aleatorios. Chris Baker 3 de enero de 2013 a las 20:45
  • 79
    ¡Se ve hermoso pero en algunos casos esto genera una cadena vacía! Si aleatorio devuelve 0, 0.5, 0.25, 0.125 ... resultará en una cadena vacía o corta. gertas 15/0313 a las 19:55
  • 76
    @gertas Esto se puede evitar(Math.random() + 1).toString(36).substring(7);George Reith 11/08/2013 a las 17:17
  • 34
    @hacklikecrack, los duplicados ocurren porque substring(7)toma los dígitos de la parte menos significativa de la cadena base-36. toString(36)parece convertir el número aleatorio en una cadena de base 36 de 16 dígitos, pero la precisión requerida para esto sería 36 ^ 16 = 7.958e24 números posibles, donde la precisión de Math.random () es solo 4.5e15 . Tomando los dígitos del extremo más significativo con .slice(2,5)resuelve esto: ejemplo de 5 dígitosLuke 4 de diciembre de 2014 a las 0:48
665

Math.random es malo para este tipo de cosas

Opción 1

Si puede hacer esto en el lado del servidor , simplemente use el módulo criptográfico -

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


opcion 2

Si tiene que hacer esto en el lado del cliente , tal vez pruebe el módulo uuid -

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

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

Opcion 3

Si tiene que hacer esto en el 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 dec.toString(16).padStart(2, "0")
}

// 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 obtener más información sobre crypto.getRandomValues:

The crypto.getRandomValues() method lets you get cryptographically strong random values. The array given as the parameter is filled with random numbers (random in its cryptographic meaning).

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 conocer la cobertura del navegador, consulte https://caniuse.com/#feat=getrandomvalues

20
  • 5
    Exactamente. Si bien un UUID está bien para asignar una ID a algo, usarlo como una cadena de caracteres aleatorios no es una gran idea por esta (y probablemente otras) razones. wmassingham 4 de agosto de 2015 a las 17:42
  • 3
    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 11 de mayo de 2017 a las 19:28
  • 7
    Debe mencionar en la respuesta que la opción 2 también necesita node.js para funcionar, no es javascript puro. Esko 21/08/18 a las 11:47
  • 8
    Si bien es más seguro criptográficamente, esto en realidad no satisface los requisitos de la pregunta porque solo genera 0-9 y af (hexadecimal), y no 0-9, az, AZ. qJake 17/10/18 a las 19:46
  • 1
    @ AneesAhmed777 dec2hexse le proporcionó un codificador de ejemplo. Depende de usted representar los bytes como elija. Actualicé la publicación con tu sugerencia. Mulan 1 dic.20 a las 17:29
212

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);
14
  • 15
    ¿Qué pasa si Math.random().toString(36)devuelve un número con menos de 5 caracteres? Michael Litvin 17 de enero de 2017 a las 11:42
  • 8
    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 algún otro lugar también. Afortunadamente, parece que al menos 51 chicos han encontrado útil esta respuesta, ¡de nada! Silver Ringvee 5 de marzo de 2017 a las 11:10
  • 6
    @rinogo Math.random () puede devolver 0 pero no 1 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…mikep 4 de agosto de 2017 a las 9:54
  • 6
    Ejecuté este código 1,000,000,000 de veces y todavía no obtuve una cadena vacía: jsfiddle.net/mtp5730r Yo diría que está bastante a salvo de obtener una cadena vacía. MacroMan 19/07/18 a las 13:39
  • 13
    Un evento que sea estadísticamente improbable no lo hace seguro. Si alguien está usando esto para cualquier actividad relacionada con la seguridad, está apostando a la improbabilidad de Math.randomno devolver 0. Espero que nunca tenga que depurar este eventoPurefan 14/03/19 a las 17:26
172

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

Primero, como han mencionado otros, 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. He aquí 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 a una cadena de base 36, es decir, utilizando los caracteres 0-9 y az.
  3. Rellenar con ceros (resuelve el primer problema).
  4. Corta el '0' inicial. prefijo y ceros de relleno adicionales.
  5. Repita la cadena suficientes veces para tener al menos N caracteres en ella (uniendo cadenas vacías con la cadena aleatoria más corta utilizada como delimitador).
  6. Corta exactamente N caracteres de la cadena.

Pensamientos adicionales:

  • Esta solución no usa 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 consiste en admitir cualquier longitud de cadena solicitada, no en 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 () estén distribuidos uniformemente (esto no es una aleatoriedad de fuerza criptográfica, en cualquier caso).
  • Es posible que no se devuelvan 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 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 frases ingeniosas de estilo funcional que se me ocurrieron. Se diferencian de la solución anterior en que:

  • Usan un alfabeto arbitrario explícito (más genérico y adecuado a 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), lo que los hace más sencillos y fáciles de entender.

Entonces, digamos que su 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:

Me parece que qubyte y Martijn de Milliano encontraron soluciones similares a este último (¡felicitaciones!), Que de alguna manera me perdí. Dado que no se ven tan cortos de un vistazo, lo dejaré aquí de todos modos en caso de que alguien realmente quiera una sola línea :-)

Además, reemplazó 'new Array' con 'Array' en todas las soluciones para reducir algunos bytes más.

8
  • ¿Por qué no agregar 1? (Math.random()+1).toString(36).substring(7);emix 8 de enero de 2015 a las 10:00
  • Porque sumar 1 no resuelve ninguno de los dos problemas discutidos aquí. Por ejemplo, (1) .toString (36) .substring (7) produce una cadena vacía. amichair 19/01/15 a las 11:36
  • El uso Math.random().toString(36).substring(2,7)da un resultado esperado que se parece más al.substring(2, n+2)Joseph Rex 13/11/15 a las 13:04
  • Array.apply(null, {length: 5}).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('')Muhammad Umer 13/11/15 a las 14:54
  • Esto es genial, pero cuando se ejecuta en Firefox con N = 16, los últimos ~ 6 dígitos terminan siendo cero ... (Pero satisface el deseo del OP de 5 caracteres aleatorios)Edward Newell 10/06/2016 a las 23:15
154

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 punto 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));
6
  • Math.random().toString(36).slice(-5);- ¿Y si Math.random()vuelve 0.0? x-ray 12 jul 2019 a las 16:00
  • @ rayos x, obtendrás "0";)Valentin Podkamennyi 13/07/19 a las 4:13
  • 2
    Exactamente. ;) Y si Math.random()devuelve 0.5el resultado es "0.i". No estoy seguro si hay otros casos extremos. Solo quería señalar que esta no es una respuesta correcta a la pregunta (5 caracteres de [a-zA-Z0-9]). x-ray 13/07/19 a las 12:27
  • 2
    @ x-ray, no voy a decir que esta sea la respuesta correcta, solo digo que esta es una versión compacta de la respuesta de @doubletap anterior. Yo personalmente utilizo (+new Date + Math.random())para prevenir este caso. De todos modos, gracias por la nota. Valentin Podkamennyi 13/07/19 a las 16:39
  • 1
    ¿Por qué no usar botanada? Hice un comentario sobre otras respuestas pero usando este caso de prueba se puede ver que va a utilizar sólo 14 caracteres de los 64 que se base 64 tiene que ofrecer:[...new Set([...Array(100000)].map(()=>btoa(Math.random()).substr(0, 5)).join(""))].sort()Or Duan 14 nov.20 a las 7:34
111

Una versión más reciente con el operador de propagación es6 :

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

  • El 30es un número arbitrario, puede elegir cualquier longitud de token que desee
  • El 36es el número de base máximo que puede pasar a numeric.toString () , lo que significa que todos los números y letras minúsculas az
  • Se 2usa para elegir el tercer índice de la cadena aleatoria que se ve así:, "0.mfbiohx64i"podríamos tomar cualquier índice después0.
4
  • ¿Podrías explicar? Especialmente, ¿por qué pasa 36 a toString () y por qué elige el tercer elemento? vuza 5 de diciembre de 2017 a las 10:55
  • agradable, pero esta solución no incluye los caracteres [AZ] como se solicitó en la pregunta, solo [a-z0-9]Nahuel Greco 3 mar.20 a las 13:02
  • @NahuelGreco puedes hacer [... Array (30)]. Map (() => Math.random (). ToString (36) [2]). Join (''). ToUpperCase ()tam.teixeira 20 de julio de 2020 a las 0:56
  • @ tam.teixeira Creo que no, la pregunta original se hizo para mayúsculas mixtas, cada carácter debe elegirse al azar del conjunto [a-zA-Z0-9]. Esta respuesta no satisface eso. Nahuel Greco 20/07/20 a las 15:13
106

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

var randomValue = randomString(5);

var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');
4
  • Aquí se puede encontrar una variante de ejemplo aquí: mediacollege.com/internet/javascript/number/random.htmlDavid 31/08/12 a las 18:17
  • 1
    bien podría disminuir lendirectamente en un whilebucledrzaus 6 de marzo de 2013 a las 14:59
  • Gracias, acabo de publicar a continuación una variación de coffeescript de este ejemplo: stackoverflow.com/a/26682781/262379Dinis Cruz 31/10/2014 a las 20:20
  • Si se van a utilizar públicamente, probablemente debería 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 18/04/2017 a las 18:22
75

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));
4
  • Me gusta esto más. Puede modificar fácilmente para aceptar parámetros adicionales y devolver solo nums, lowers o caps. No creo que el estilo ultracomprimido sea necesariowhile(s.length< L) s+= randomchar();mastaBlasta 17/01/2014 a las 19:24
  • 3
    También while(L--)lo harévsync 17 de junio de 2014 a las 12:30
  • 3
    Es mejor usar el número más robusto 'A'.charCodeAt(0)que el mágico 55(y lo mismo para el 61). Particularmente porque, en mi plataforma de todos modos, el número mágico que regresa es 65. Ese código también se auto-documentará mejor. Grumdrig 10 de julio de 2017 a las 6:00
  • Creé una variante optimizada para la minificación (46 bytes más pequeña) de su implementación aquí: stackoverflow.com/a/52412162Waruyama 20 de septiembre de 2018 a las 7:18
68

Generador de cadenas aleatorias (alfanumérico | alfanumérico | 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 A / N, A, N deseada , desglosémoslo en 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 de 0 a 61 (0..9 + A..Z + a..z = 62)
  • Cree una lógica condicional para Ajustar / corregirrand (ya que es 0..61) incrementándola en algún número (vea los ejemplos a continuación) para recuperar el CharCodenúmero correcto y el Carácter relacionado.
  • Dentro del bucle concatenar 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 aleatorio para obtener los rangos de charCode correctos :

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

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))
1
  • 1
    Por una razón que no pude identificar, x.toString(36)--- como se usa en las respuestas anteriores --- no estaba generando de manera confiable los mismos caracteres cuando comparé las salidas de dos aplicaciones que tenían diferentes versiones de ES, y esta función solucionó esto para yo ya que no lo usa .toString()! Harley Lang 4 de febrero a las 22:13
41

La forma más sencilla es:

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

Esto genera cadenas aleatorias de 5 caracteres según la hora actual. La salida de ejemplo es 4mtxjo 4mv90o4mwp1

El problema con esto es que si lo llama 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. La salida de ejemplo es como 30jzmo 1r591o4su1a

De ambas formas, la primera parte genera un número aleatorio. La .toString(36)parte convierte el número en una representación base36 (alfadecimal) del mismo.

5
  • 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 opta por proporcionar una nueva respuesta, debe tener especial cuidado para asegurarse de que su respuesta esté bien explicada y documentada. Claies 11/03/15 a las 22:01
  • 1
    Si usa Date, ¿por qué no lo usa como:(+new Date).toString(36)seniorpreacher 15/07/2015 a las 13:47
  • Me gusta su solución de números aleatorios, pero 9e6 ofrece solo 9 millones de posibilidades sobre los 60,4 millones de 5 dígitos (36 ^ 5), por lo que podría reemplazarlo (0|Math.random()*6.04e7).toString(36)para cubrirlo. Le Droid 5 de ene. De 2016 a las 13:54
  • 1
    Quería una cadena aleatoria larga con una rutina lo más corta posible (para una demostración de código) que no necesita ser criptográficamente sorprendente, solo producir una buena "pelusa" visual aleatoria. Me gusta más esta respuesta (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 27 feb 2016 a las 19:11
  • 1
    un reparo que tengo con esta respuesta es que no usará [AZ], que está en la pregunta original. user.friendly 11/10/2017 a las 22:16
30

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

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

Se producirán letras minúsculas, mayúsculas y números.

2
  • 3
    Supongo que Math.random () podría conducir a una cadena base64 con muy pocos caracteres. Leif 25 de junio de 2018 a las 7:57
  • Agregando el comentario de @Leif, esto solo generará números entre 1-5 y solo 19 de 52 letras (mayúsculas y minúsculas). Para probar, simplemente ejecútelo varias veces, Setpara ver caracteres únicos y luego ordenar. un trazador de líneas para eso:[...new Set([...Array(100000)].map(()=>btoa(Math.random()).substr(5, 5)).join(""))].sort()Or Duan 14 nov.20 a las 7:19
24

Aquí hay algunas frases sencillas. Cambie 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"]();});
0
24

Sé que todos ya lo han hecho bien, pero tenía ganas de intentarlo de la manera más liviana posible (ligero en el código, no en la 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));

Se necesita un poco de tiempo para entenderlo, pero creo que realmente muestra lo increíble que es la sintaxis de JavaScript.

3
  • 23
    Si está tratando de mantener el código corto, ¿por qué escribir current = current ? current : '';cuando puede escribir current = current || ''? CaffGeek 8 de agosto de 2011 a las 13:45
  • 10
    ya que estamos hablando de microoptimización aquí, en realidad sugeriría omitir la asignación de variables por completo si no es necesario:current || (current = '');Thomas Heymann 13 dic 2013 a las 10:36
  • Intentar la microoptimizació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 26/06/19 a las 9:52
18

En caso de que alguien esté interesado en un one-liner (aunque no formateado 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í es 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).

1
  • 20
    Cada programa javascript es un 'one-liner' si lo formatea como talhacklikecrack 1 de diciembre de 2013 a las 14:56
18

Si está utilizando Lodash o Underscore , entonces es tan simple:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
2
  • 8
    Usos de Lodash_.sampleSize('asdfgh',5).join('')marlo 24 de agosto de 2016 a las 4:08
  • 4
    En realidad, esta no es una buena solución, porque por documento, cada carácter proviene de un índice único. Eso significa que no es verdaderamente aleatorio, ya que ningún personaje puede repetirse. random_user_name 4/11/2017 a las 21:44
18

Genere una Base-62cadena alfanumérica aleatoria segura :

function generateUID(length)
{
    return window.btoa(Array.from(window.crypto.getRandomValues(new Uint8Array(length * 2))).map((b) => String.fromCharCode(b)).join("")).replace(/[+/]/g, "").substring(0, length);
}

console.log(generateUID(22)); // "yFg3Upv2cE9cKOXd7hHwWp"
console.log(generateUID(5)); // "YQGzP"
14

Este es el método que creé.
Creará una cadena que contiene caracteres tanto en mayúsculas como en minúsculas.
Además, he incluido la función que también creará una cadena alfanumérica.

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)));
}
2
  • Con esta función, nunca puede obtener una letra mayúscula mayor que 'M' o una letra minúscula menor que 'n'. erkanyildiz 21/01/15 a las 14:21
  • ¿En serio? ¡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), todavía hace lo que queremos que haga, que es todo lo que importa, pero sí, proporcionará un actualizar, gracias. Adam 27/07/15 a las 11:50
14
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
0
14

Mejorada la respuesta de @ Andrew arriba:

Array.from({ length : 1 }, () => Math.random().toString(36)[2]).join('');

La conversión de base 36 del número aleatorio es inconsistente, por lo que la selección de un solo índice corrige eso. Puede cambiar la longitud de una cuerda con la longitud exacta deseada.

1
  • 1
    Bonito trazador de líneas, ¡gracias! biomiker 15 de enero a las 19:45
13

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

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
1
  • 6
    Esto hará que el valor devuelto tenga todos los caracteres únicos. Además, la longitud de la cadena está limitada hasta la longitud de var posible. Yefu 21/11/2016 a las 1:37
13

Un trazador de líneas:

Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
3
  • Para hacerlo más corto, cambie el argumento Array(15)a un valor más pequeño. Por ejemplo: Array(4). arkadyt 3 abr.20 a las 18:40
  • 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 todos juntos. Siscia 11 de mayo de 2020 a las 20:17
  • Solución errónea, no se generan caracteres en mayúscula. Nahuel Greco 31 de julio a las 16:20
10

Algoritmo rápido y mejorado. No garantiza 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;
}
2
  • 3
    Gran respuesta, pero la probabilidad no es uniforme. Hay 62 caracteres posibles y crypto.getRandomValuesdevuelve uno de 256 valores únicos. Debido a que 256 no se divide 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 juego de caracteres. De todos modos, gran trabajo, esta respuesta necesita mucho más amor :)TeWu 19 de mayo de 2017 a las 12:07
  • agregar - y _ es una gran idea, ya que le proporcionará el conjunto completo de base64 seguro para URLcowbert 14 dic 2017 a las 23:55
9

¿Qué tal este pequeño truco compacto?

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

Necesita que Array.applyesté allí para engañar a la matriz vacía para que sea una matriz de indefinidos.

Si está codificando para ES2015, entonces construir la matriz es un poco más simple:

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

Puede recorrer una matriz de elementos y agregarlos de forma recursiva 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));
8
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 .

2
  • Para mí, esto siempre genera cadenas aleatorias con strLength - 1: - /AlexGrafe 22/11/2013 a las 11:43
  • 4
    Cambiar de --strLengtha strLength--me lo soluciona. AlexGrafe 22/11/2013 a las 11:43
8

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

Hay dos formas principales de obtener cadenas estrictamente únicas : de forma determinista (que no es aleatoria) y almacenar / comparar (que es oneroso). qué hacemos? Renunciamos al fantasma. En su lugar, optamos por la unicidad probabilística . Es decir, aceptamos que existe algún riesgo (por pequeño que sea) de que nuestras cadenas no sean únicas. Aquí es donde resulta útil comprender la probabilidad de colisión y la entropía .

Así que reformularé la necesidad invariable como la necesidad de una cierta cantidad de cadenas con un pequeño riesgo de repetición. Como ejemplo concreto, digamos 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, digamos un riesgo de menos de 1 en un billón de posibilidades de repetición. Entonces, ¿qué longitud de cuerda necesitas? Bueno, esa pregunta está subespecificada ya que depende de los caracteres utilizados. Pero lo que es más importante, está equivocado. Lo que necesita es una especificación de la entropía de las cadenas, no su longitud. La entropía se puede relacionar directamente 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 tienen 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 juego de caracteres con 32 caracteres por defecto. Hay otros conjuntos de caracteres predefinidos y también puede especificar sus propios caracteres. Por ejemplo, generando ID con la misma entropía que arriba pero usando 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 juego de caracteres utilizado. El riesgo de repetición en el número especificado de cadenas potenciales es el mismo. Las longitudes de las cuerdas no lo son. Y lo mejor de todo es que 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.

1
  • ¡Gracias! Su comentario me hizo darme cuenta de que no debería generar ID al azar. Parece que nanoides mucho más popular entropy-stringy me parece igual de bueno para mis propósitos. Altay_H 4 dic.20 a las 23:18
7

Caracteres alfanuméricos que no distinguen entre mayúsculas y minúsculas:

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 asegura la longitud de la cadena.

Todos los caracteres sensibles a mayúsculas y minúsculas:

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
1
  • 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, para que el resultado de la función sea más configurable. Denis.Sabolotni 11/10/2018 a las 11:40
6

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

Soporte solo 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.

6

Un trazador de líneas [az]:

String.fromCharCode(97 + Math.floor(Math.random() * 26))
1
  • Aún necesita componer la cadena con la longitud solicitada. Y esto solo genera caracteres aleatorios a partir de [ab] minúsculas. ¿Qué pasa con las mayúsculas y los números como también se preguntó en la pregunta? denik1981 1 de junio a las 18:35