node - letras aleatorias javascript
Generar cadenas/caracteres aleatorios en JavaScript (30)
Quiero una cadena de 5 caracteres compuesta de caracteres seleccionados al azar del conjunto [a-zA-Z0-9]
.
¿Cuál es la mejor manera de hacer esto con JavaScript?
Generador de cadenas aleatorias (Alfanumérico | Alfa | Numérico)
/**
* RANDOM STRING GENERATOR
*
* Info: http://.com/a/27872144/383904
* Use: randomString(length [,"A"] [,"N"] );
* Default: return a random alpha-numeric string
* Arguments: If you use the optional "A", "N" flags:
* "A" (Alpha flag) return random a-Z string
* "N" (Numeric flag) return random 0-9 string
*/
function randomString(len, an){
an = an&&an.toLowerCase();
var str="", i=0, min=an=="a"?10:0, max=an=="n"?10:62;
for(;i++<len;){
var r = Math.random()*(max-min)+min <<0;
str += String.fromCharCode(r+=r>9?r<36?55:61:48);
}
return str;
}
randomString(10); // "4Z8iNQag9v"
randomString(10, "A"); // "aUkZuHNcWw"
randomString(10, "N"); // "9055739230"
Que te diviertas. demo jsbin
Mientras que lo anterior usa comprobaciones adicionales para la salida deseada (A / N, A, N), analicemos lo esencial (sólo alfanumérico) para una mejor comprensión:
- Cree una función que acepte un argumento (longitud deseada del resultado aleatorio de la cadena)
- Crea una cadena vacía como
var str = "";
concatenar caracteres aleatorios - Dentro de un bucle, cree un número de índice de
rand
de 0 a 61 (0..9 + A..Z + a..z = 62) - Cree una lógica condicional para Ajustar / corregir
rand
(ya que es 0..61) incrementándola en algún número (vea los ejemplos a continuación) para recuperar el número deCharCode
correcto y el carácter relacionado. - Dentro del bucle concatenar para
str
unString.fromCharCode( incremented rand )
Imaginemos la tabla de personajes y sus rangos :
_____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 )
ofrece un rango de 0..61
(lo que necesitamos). ¿Cómo arreglar (incrementar) el azar para obtener los rangos de caracteres 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 de arriba:
rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ;
// rand += true ? ( true ? 55 else 61 ) else 48 ;
Si siguió la explicación anterior, debería poder crear este fragmento de código alfanumérico :
function randomString( len ) {
var str = ""; // String result
for(var i=0; i<len; i++){ // Loop `len` times
var rand = Math.floor( Math.random() * 62 ); // random: 0..61
var charCode = rand+= rand>9? (rand<36?55:61) : 48; // Get correct charCode
str += String.fromCharCode( charCode ); // add Character to str
}
return str; // After all loops are done, return the concatenated string
}
console.log( randomString(10) ); // "7GL9F0ne6t"
function randomString( n ) {
var r="";
while(n--)r+=String.fromCharCode((r=Math.random()*62|0,r+=r>9?(r<36?55:61):48));
return r;
}
Corto, fácil y fiable.
Devuelve exactamente 5 caracteres aleatorios, a diferencia de algunas de las respuestas más valoradas que se encuentran aquí.
Math.random().toString(36).substr(2, 5);
¿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('''');
Necesitas el Array.apply
allí para engañar a la matriz vacía para que sea una matriz de indefinidos.
Si está codificando para ES2015, construir el array es un poco más simple:
var randomString = Array.from({ length: stringLength }, pickRandom).join('''');
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;
}
Llama con el juego de caracteres predeterminado [a-zA-Z0-9] o envía el tuyo:
var randomValue = randomString(5);
var randomValue = randomString(5, ''PICKCHARSFROMTHISSET'');
Algoritmo rápido y mejorado. No garantiza uniformidad (ver comentarios).
function getRandomId(length) {
if (!length) {
return '''';
}
const possible =
''ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'';
let result = '''';
let array;
if (''Uint8Array'' in self && ''crypto'' in self && length <= 65536) {
array = new Uint8Array(length);
self.crypto.getRandomValues(array);
} else {
array = new Array(length);
for (let i = 0; i < length; i++) {
array[i] = Math.floor(Math.random() * 62);
}
}
for (let i = 0; i < length; i++) {
result += possible.charAt(array[i] % 62);
}
return result;
}
Aquí está el método que he creado.
Creará una cadena que contiene caracteres en mayúsculas y 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;
}
Actualizar julio 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)));
}
Aquí hay algunos liners fáciles. Cambie la new Array(5)
para establecer la longitud.
Incluyendo 0-9a-z
new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36);})
Incluyendo 0-9a-zA-Z
new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();});
Aquí hay un script de prueba para la respuesta # 1 (gracias @ csharptest.net)
la secuencia de comandos ejecuta makeid()
1 million
veces y, como se puede ver, 5 no es algo único. ejecutarlo con una longitud de 10 caracteres es bastante confiable. Lo he corrido unas 50 veces y todavía no he visto un duplicado :-)
nota: el límite de tamaño de la pila de nodos supera los 4 millones, por lo que no puede ejecutar estos 5 millones de veces que nunca terminará
function makeid()
{
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 5; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
ids ={}
count = 0
for (var i = 0; i < 1000000; i++) {
tempId = makeid();
if (typeof ids[tempId] !== ''undefined'') {
ids[tempId]++;
if (ids[tempId] === 2) {
count ++;
}
count++;
}else{
ids[tempId] = 1;
}
}
console.log("there are "+count+ '' duplicate ids'');
Aquí hay una mejora en la excelente respuesta de doubletap . El original tiene dos inconvenientes que se abordan 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 interrumpir 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 usar 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:
- Elija un número aleatorio en el rango [0,1), es decir, entre 0 (incluido) y 1 (exclusivo).
- Convierta el número a una cadena base-36, es decir, use los caracteres 0-9 y az.
- Pad con ceros (resuelve el primer problema).
- Cortar el ''0'' inicial. Prefijo y relleno adicional de ceros.
- Repita la cadena las veces suficientes para tener al menos N caracteres (uniendo cadenas vacías con la cadena aleatoria más corta utilizada como delimitador).
- Cortar exactamente N caracteres de la cadena.
Más pensamientos:
- 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 aleatoriedad de fuerza criptográfica, en ningún caso).
- No todas las cadenas posibles de tamaño N pueden devolverse. En la segunda solución esto es obvio (ya que la cadena más pequeña simplemente se duplica), 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. De nuevo, 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 líneas 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 para la pregunta original que pedía letras mayúsculas y minúsculas).
- Todas las cadenas de longitud N tienen una probabilidad igual 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 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 puedes elegir el que sea más intuitivo para ti:
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 encontraron soluciones similares a esta última (¡felicitaciones!), Que de alguna manera me perdí. Ya que no se ven tan cortos de un vistazo, lo dejo 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 eliminar algunos bytes más.
Creo que esto funcionará para usted:
function makeid() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 5; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
console.log(makeid());
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 la longitud de la cadena . Las preguntas en sí rara vez revelan por qué se necesitan las cadenas aleatorias, pero le desafiaría a que rara vez necesite cadenas aleatorias de longitud, por ejemplo 8. Lo que siempre necesita es un 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 : determinísticamente (que no es aleatoria) y almacenar / comparar (que es onerosa). qué hacemos? Renunciamos al fantasma. Vamos con unicidad probabilística en su lugar. Es decir, aceptamos que existe un riesgo (por pequeño que sea) de que nuestras cadenas no sean únicas. Aquí es donde entender la probabilidad de colisión y la entropy son útiles.
Así que reformularé la necesidad invariable como la necesidad de un 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, 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 más importante, es un error. Lo que necesita es una especificación de la entropía de las cadenas, no su longitud. La entropía puede relacionarse directamente con la probabilidad de una repetición en algún número de cadenas. La longitud de la cadena no puede.
Y aquí es donde una biblioteca como EntropyString puede ayudar. Para generar IDs aleatorios que tengan menos de 1 en un billón de posibilidades de repetición en 5 millones de cadenas utilizando 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-string
utiliza un conjunto de caracteres con 32 caracteres por defecto. Hay otros conjuntos de caracteres predefinidos, y también puede especificar sus propios caracteres. Por ejemplo, generar 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 conjunto de caracteres utilizado. El riesgo de repetición en el número especificado de cadenas posibles 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.
En el caso de que alguien esté interesado en una sola línea (aunque no esté formateada como tal para su conveniencia) que asigne la memoria a la vez (pero tenga en cuenta que para cadenas pequeñas no importa), aquí está 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 5
por la longitud de la cadena que desea. Gracias a @AriyaHidayat en este post por la solución a la función de map
que no funciona en la matriz dispersa creada por Array(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>
Generar 10 caracteres de cadena larga. 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;
}
La forma más sencilla es:
(new Date%9e6).toString(36)
Esto genera cadenas aleatorias de 5 caracteres basadas en la hora actual. La salida de ejemplo es 4mtxj
o 4mv90
o 4mwp1
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 30jzm
o 1r591
o 4su1a
En ambos sentidos la primera parte genera un número aleatorio. La parte .toString(36)
el número en una representación base36 (alphadecimal) de la misma.
La solución más compacta, porque la slice
es más corta que la substring
. Restar del final de la cadena permite evitar el símbolo de punto flotante generado por developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… función developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… :
Math.random().toString(36).slice(-5);
o incluso
(+new Date).toString(36).slice(-5);
// Using Math.random
console.log(Math.random().toString(36).slice(-5));
// Using new Date
console.log((+new Date).toString(36).slice(-5));
No encontré una solución limpia para admitir tanto mayúsculas como minúsculas.
Soporte en minúsculas solamente:
Math.random().toString(36).substr(2, 5)
Basándose en esa solución para admitir en minúsculas y mayúsculas:
Math.random().toString(36).substr(2, 5).split('''').map(c => Math.random() < 0.5 ? c.toUpperCase() : c).join('''');
Cambie los 5
en substr(2, 5)
para ajustar la longitud que necesita.
Para cumplir con el requisito [a-zA-Z0-9] y la longitud = 5 uso
btoa(Math.random()).substr(5, 5);
Se producirán letras minúsculas, mayúsculas y números.
Puede recorrer un conjunto 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));
Puedes usar coderain . Es una biblioteca para generar códigos aleatorios de acuerdo con el patrón dado. Use #
como marcador de posición para los caracteres en mayúsculas y minúsculas, así como los dígitos:
var cr = new CodeRain("#####");
console.log(cr.next());
Hay otros marcadores de posición como A
para las letras mayúsculas o 9
para los dígitos.
Lo que puede ser útil es que llamar a .next()
siempre le dará 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 .
Revelación completa: soy el autor de coderain.
Qué tal algo como esto: Date.now().toString(36)
No muy aleatorio, pero corto y bastante único cada vez que lo llamas.
Sé que todos ya lo han entendido bien, pero sentí que tenía ganas de hacerlo 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 comprenderlo, pero creo que realmente muestra cuán impresionante es la sintaxis de JavaScript.
Si estás usando Lodash o Underscore , entonces es tan simple:
var randomVal = _.sample(''ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'', 5).join('''');
Suponiendo que utilice Underscore , es posible generar de forma elegante una cadena aleatoria en solo dos líneas:
var possible = ''ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'';
var random = _.sample(possible, 5).join('''');
Una nueva versión con operador de propagación es6 :
[...Array(30)].map(() => Math.random().toString(36)[3]).join('''')
- El
30
es un número arbitrario, puede elegir la longitud de token que desee - El
36
es el número de radix máximo que puede pasar a numeric.toString() , lo que significa todos los números y las letras en minúscula. - El
3
se usa para elegir el tercer número de la cadena aleatoria que se ve así:"0.mfbiohx64i"
, podríamos tomar cualquier índice después de0.
Math.random es malo para este tipo de cosas
Opción 1
Si puede hacer esto en el lado del servidor , solo use el módulo crypto
var crypto = require("crypto");
var id = crypto.randomBytes(20).toString(''hex'');
// "bb5dc8842ca31d4603d6aa11448d1654"
La cadena resultante será dos veces más larga que los bytes aleatorios que genere; Cada byte codificado en hexadecimal es de 2 caracteres. 20 bytes serán 40 caracteres de hex.
opcion 2
Si tiene que hacer este 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 este lado del cliente y no tiene que admitir navegadores antiguos, puede hacerlo sin dependencias
// dec2hex :: Integer -> String
function dec2hex (dec) {
return (''0'' + dec.toString(16)).substr(-2)
}
// generateId :: Integer -> String
function generateId (len) {
var arr = new Uint8Array((len || 40) / 2)
window.crypto.getRandomValues(arr)
return Array.from(arr, dec2hex).join('''')
}
console.log(generateId())
// "82defcf324571e70b0521d79cce2bf3fffccd69"
console.log(generateId(20))
// "c1a050a4cd1556948d41"
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));
let r = Math.random().toString(36).substring(7);
console.log("random", r);
Ampliando el elegante ejemplo de Doubletap respondiendo a los problemas que Gertas y Dragon mencionaron. Simplemente agregue en un bucle while para probar esas raras circunstancias nulas y limite los caracteres a cinco.
function rndStr() {
x=Math.random().toString(36).substring(7).substr(0,5);
while (x.length!=5){
x=Math.random().toString(36).substring(7).substr(0,5);
}
return x;
}
Aquí hay un jsfiddle que le alerta con un resultado: http://jsfiddle.net/pLJJ7/
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 tan limpio como será posible. También es rápido, http://jsperf.com/ay-random-string .