Gere string / caracteres aleatórios em JavaScript


1780

Eu quero uma seqüência de 5 caracteres composta por caracteres escolhidos aleatoriamente do conjunto [a-zA-Z0-9].

Qual é a melhor maneira de fazer isso com JavaScript?


48
Aviso: Nenhuma das respostas tem true-randomresultado! Eles são apenas pseudo-random. Ao usar seqüências aleatórias para proteção ou segurança, não use nenhuma delas !!! Tente uma destas APIs: random.org
Ron van der Heijden

48
Math.random (). ToString (36) .replace (/ [^ az] + / g, '')
Muaz Khan

13
Por favor, coloque a solução em uma solução.
Chryss

216
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
Friedrich

12
Nota A API de aleatoriedade de criptografia da web HTML5 fornece aleatoriedade real.
Mikemaccana

Respostas:


2433

Eu acho que isso funcionará para você:

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


117
Isso é bom para cadeias curtas, mas cuidado, usar +=cadeias como essa faz com que ele tenha comportamento O (n ^ 2). Se você deseja criar seqüências mais longas, crie uma matriz de caracteres individuais e junte-os no final.
dan_waterworth

97
@dan_waterworth Provavelmente não importa em quase qualquer caso: codinghorror.com/blog/2009/01/...
Alex Reece

7
@dan_waterworth, na verdade, +=é muitas vezes mais rápido por algum motivo, mesmo usado dentro de loops - jsperf.com/join-vs-concatenation
Konrad Borowski

18
@JonathanPaulson Mostre-me os números . Consulte o comentário anterior com um link jsperf ou jsperf.com/sad-tragedy-of-microoptimization ou sitepen.com/blog/2008/05/09/string-performance-an-analysis etc. Além disso, esta questão envolve apenas 5 concatenações .
Alex Reece #

11
@codenamejames Por favor , não use isso em sua senha de salgar. É apenas pseudo-aleatório não seguro. Supondo que você esteja usando o Node (nem sei por onde começar se estiver usando sal no lado do cliente), use-o crypto.
Hydrothermal

2330

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

Nota: O algoritmo acima tem os seguintes pontos fracos:

  • Ele gerará algo entre 0 e 6 caracteres devido ao fato de que os zeros à direita são removidos ao especificar pontos flutuantes.
  • Depende profundamente do algoritmo usado para especificar números de ponto flutuante, o que é terrivelmente complexo. (Consulte o artigo "Como imprimir números de ponto flutuante com precisão" .)
  • Math.random()pode produzir resultados previsíveis ("aparência aleatória", mas não realmente aleatória), dependendo da implementação. A sequência resultante não é adequada quando você precisa garantir exclusividade ou imprevisibilidade.
  • Mesmo que tenha produzido seis caracteres uniformemente aleatórios e imprevisíveis, você pode esperar ver uma duplicata depois de gerar apenas cerca de 50.000 strings, devido ao paradoxo do aniversário . (sqrt (36 ^ 6) = 46656)

276
Math.random().toString(36).substr(2, 5), porque .substring(7)faz com que ele tenha mais de 5 caracteres. Pontos completos, ainda!
dragon

81
@Scoop O toStringmétodo de um tipo de número em javascript usa um parâmetro opcional para converter o número em uma determinada base. Se você passar dois, por exemplo, verá seu número representado em binário. Semelhante ao hex (base 16), a base 36 usa letras para representar dígitos além de 9. Ao converter um número aleatório em base 36, você terminará com várias letras e números aparentemente aleatórios.
Chris Baker

76
Parece bonito, mas em alguns casos isso gera uma string vazia! Se retornos aleatórios 0, 0,5, 0,25, 0,125 ... resultarão em uma sequência curta ou vazia.
gertas

67
@gertas Isso pode ser evitado por(Math.random() + 1).toString(36).substring(7);
George Reith

84
Cara, isso é praticamente inútil. Execute-o apenas 1000000 vezes e você geralmente obtém 110000 ocorrências de repetição: var values ​​= {}, 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 ("TOTAL DUPLICATES", duplicateCount);
precisa saber é o seguinte

463

Math.random é ruim para esse tipo de coisa

Opção 1

Se você puder fazer isso no lado do servidor , use o módulo de criptografia -

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

// "bb5dc8842ca31d4603d6aa11448d1654"

A sequência resultante será duas vezes maior que os bytes aleatórios que você gerar; cada byte codificado em hexadecimal tem 2 caracteres. 20 bytes terão 40 caracteres hexadecimais.


opção 2

Se você precisar fazer isso do lado do cliente , talvez tente o módulo uuid -

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

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

Opção 3

Se você precisar fazer isso no lado do cliente e não precisar dar suporte a navegadores antigos, poderá fazê-lo sem dependências -

// 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 mais informações sobre crypto.getRandomValues-

O crypto.getRandomValues()método permite obter valores aleatórios criptograficamente fortes. A matriz fornecida como parâmetro é preenchida com números aleatórios (aleatório em seu significado criptográfico).

Aqui está um pequeno exemplo de console -

> var arr = new Uint8Array(4) # make array of 4 bytes (values 0-255)
> arr
Uint8Array(4) [ 0, 0, 0, 0 ]

> window.crypto
Crypto { subtle: SubtleCrypto }

> window.crypto.getRandomValues()
TypeError: Crypto.getRandomValues requires at least 1 argument, but only 0 were passed

> window.crypto.getRandomValues(arr)
Uint8Array(4) [ 235, 229, 94, 228 ]

Para suporte ao IE11, você pode usar -

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

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


4
Exatamente. Enquanto um UUID é bom para atribuir um ID a uma coisa, usá-lo como uma sequência de caracteres aleatórios não é uma boa idéia por esse (e provavelmente por outros) motivos.
wmassingham

2
Não é necessário .map()na Opção 3. Array.from(arr, dec2hex).join('')=== Array.from(arr).map(dec2hex).join(''). Obrigado por me apresentar estas características :-)
Fred Gandt

6
Você deve mencionar na resposta que a opção 2 também precisa do node.js para funcionar, não é um javascript puro.
Esko

5
Embora seja mais criptograficamente seguro, isso não satisfaz os requisitos da pergunta, porque gera apenas 0-9 e af (Hexadecimal), e não 0-9, az, AZ.
qJake

1
O requiremódulo não pode ser usado apenas no lado do servidor?
aJetHorn 18/02/19

173

Curto, fácil e confiável

Retorna exatamente 5 caracteres aleatórios, ao contrário de algumas das respostas mais bem avaliadas encontradas aqui.

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

9
E se Math.random().toString(36)retornar um número com menos de 5 caracteres?
Michael Litvin

3
Bem, essa é uma acusação interessante do @ Aperçu, não estou dizendo que inventei a solução, mas uso-a em meus projetos há anos. E isso não tem nada a ver com o comentário que você mencionou. E tenho certeza de que, no SO, o que importa é a informação mais útil no lugar certo e mesmo que ela já exista em algum outro lugar também. Felizmente, parece que pelo menos 51 caras acharam esta resposta útil, de nada!
Silver Ringvee

3
Para evitar string vazia em caso de Math.random () retorna 0 você pode usarfunction getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
Mikep

5
@rinogo Math.random () pode retornar 0, mas não 1 developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…
mikep

6
Eu corri esse código 1.000.000.000 de vezes e ainda não obtive uma sequência vazia: jsfiddle.net/mtp5730r Eu diria que você está bem seguro de obter uma sequência vazia.
`` #

157

Aqui está uma melhoria na excelente resposta do doubletap . O original tem duas desvantagens abordadas aqui:

Primeiro, como outros já mencionaram, há uma pequena probabilidade de produzir cadeias curtas ou mesmo uma cadeia vazia (se o número aleatório for 0), o que pode interromper o seu aplicativo. Aqui está uma solução:

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

Segundo, o original e a solução acima limitam o tamanho da string N a 16 caracteres. A seguir, retornará uma sequência de tamanho N para qualquer N (mas observe que usar N> 16 não aumentará a aleatoriedade nem diminuirá a probabilidade de colisões):

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

Explicação:

  1. Escolha um número aleatório no intervalo [0,1), ou seja, entre 0 (inclusive) e 1 (exclusivo).
  2. Converta o número em uma string de base 36, ou seja, usando os caracteres de 0 a 9 e az.
  3. Almofada com zeros (resolve o primeiro problema).
  4. Corte o '0' principal prefixo e zeros de preenchimento extra.
  5. Repita a sequência de vezes o suficiente para ter pelo menos N caracteres (unindo cadeias vazias com a menor sequência aleatória usada como delimitador).
  6. Fatie exatamente N caracteres da sequência.

Pensamentos adicionais:

  • Esta solução não usa letras maiúsculas, mas em quase todos os casos (sem trocadilhos) não importa.
  • O comprimento máximo da string em N = 16 na resposta original é medido no Chrome. No Firefox, é N = 11. Mas, como explicado, a segunda solução é oferecer suporte a qualquer comprimento de string solicitado, não adicionar aleatoriedade, por isso não faz muita diferença.
  • Todas as seqüências retornadas têm uma probabilidade igual de serem retornadas, pelo menos na medida em que os resultados retornados por Math.random () sejam distribuídos igualmente (isso não é aleatoriedade de força criptográfica, em qualquer caso).
  • Nem todas as seqüências possíveis de tamanho N podem ser retornadas. Na segunda solução, isso é óbvio (uma vez que a cadeia menor está simplesmente sendo duplicada), mas também na resposta original isso é verdade, pois na conversão para a base 36 os últimos bits podem não fazer parte dos bits aleatórios originais. Especificamente, se você observar o resultado de Math.random (). ToString (36), notará que o último caractere não é distribuído igualmente. Novamente, em quase todos os casos, isso não importa, mas cortamos a sequência final desde o início, e não o final da sequência aleatória, para que as sequências curtas (por exemplo, N = 1) não sejam afetadas.

Atualizar:

Aqui estão algumas outras frases de estilo funcional que eu criei. Eles diferem da solução acima em que:

  • Eles usam um alfabeto arbitrário explícito (mais genérico e adequado à pergunta original que solicita letras maiúsculas e minúsculas).
  • Todas as cadeias de comprimento N têm uma probabilidade igual de serem retornadas (ou seja, as cadeias não contêm repetições).
  • Eles são baseados em uma função de mapa, e não no truque toString (36), que os torna mais diretos e fáceis de entender.

Então, digamos que seu alfabeto de escolha seja

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Então, esses dois são equivalentes entre si, para que você possa escolher o que for mais intuitivo para você:

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

e

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

Editar:

Parece que o qubyte e o Martijn de Milliano apresentaram soluções semelhantes a esta (parabéns!), Das quais de alguma forma eu perdi. Como eles não parecem tão breves, deixarei aqui de qualquer maneira, caso alguém realmente queira uma frase :-)

Além disso, substituiu 'new Array' por 'Array' em todas as soluções para economizar mais alguns bytes.


Por que não apenas adicionar 1? (Math.random()+1).toString(36).substring(7);
Emix

Como adicionar 1 não resolve nenhum dos dois problemas discutidos aqui. Por exemplo, (1) .toString (36) .substring (7) produz uma sequência vazia.
Amichair

Usando Math.random().toString(36).substring(2,7)dá um resultado esperado que é mais parecido com o.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

Isso é ótimo, mas quando executado no Firefox com N = 16, os últimos ~ 6 dígitos acabam sendo zero ... (Mas satisfaz o desejo do OP por 5 caracteres aleatórios.)
Edward Newell

128

A solução mais compacta, porque sliceé mais curta que substring. Subtrair do final da string permite evitar o símbolo de ponto flutuante gerado pela randomfunção:

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

ou mesmo

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

Atualização: adicionada mais uma abordagem usando o 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));


Math.random().toString(36).slice(-5);- E se Math.random()voltar 0.0?
raio-x

@ raio-x, você receberá "0";)
Valentin Podkamennyi

2
Exatamente. ;) E se Math.random()retorna 0.5o resultado é "0.i". Não tenho certeza se existem outros casos extremos. Só queria ressaltar que esta não é uma resposta correta para a pergunta (5 caracteres de [a-zA-Z0-9]).
raio-x

2
@ raio-x, não vou dizer que esta é a resposta certa, estou apenas dizendo que esta é uma versão compacta da resposta @doubletap acima. Eu pessoalmente uso (+new Date + Math.random())para evitar esse caso. De qualquer forma, obrigado pela nota.
Valentin Podkamennyi

1
Este. Não sei por que outras respostas exigem tanto código
john ktejik 29/04

100

Algo assim deve 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;
}

Ligue com o conjunto de caracteres padrão [a-zA-Z0-9] ou envie você mesmo:

var randomValue = randomString(5);

var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');

Uma variante do exemplo aqui pode ser encontrada aqui: mediacollege.com/internet/javascript/number/random.html
David

1
pode muito bem diminuir lendiretamente em um whilecircuito
drzaus

Obrigado, acabei de postar abaixo uma variação de coffeescript deste exemplo: stackoverflow.com/a/26682781/262379
Dinis Cruz

Se eles forem usados ​​publicamente, provavelmente você deve remover as vogais. Um pouco menos de entropia, mas muito mais seguro, pois você não pode gerar nenhuma palavra que possa ofender as pessoas. É por isso que gosto disso, pois posso enviar minha própria sequência de caracteres. Bom trabalho.
Nate Bunney

Muito hardcore, funcionou para mim, obrigado!
Zaki Mohammed

73

Uma versão mais recente com o operador de propagação es6 :

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

  • O 30número é arbitrário, você pode escolher qualquer tamanho de token que desejar
  • O 36é o número máximo de radix que você pode passar para numeric.toString () , que significa todos os números e letras minúsculas de az
  • O 2é usado para escolher o 3º índice da sequência aleatória que se parece com isso "0.mfbiohx64i":, poderíamos pegar qualquer índice depois0.

Você poderia explicar? Especialmente por que você passa 36 para toString () e por que escolhe o terceiro elemento?
vuza

5
esta é a melhor solução
finalista

legal, mas essa solução não inclui caracteres [AZ] conforme a pergunta solicitada, apenas [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));


Eu gosto mais disso. Você pode modificar facilmente para aceitar parâmetros extras e retornar apenas números, abaixamentos ou caps. Eu não acho que o estilo ultra-comprimido é necessáriowhile(s.length< L) s+= randomchar();
mastaBlasta

3
Também o while(L--)fará
vsync

1
Melhor usar o número mais robusto 'A'.charCodeAt(0)do que o mágico 55(e da mesma forma para o 61). Principalmente porque, na minha plataforma, o número mágico que retorna é 65. Esse código se auto-documentará melhor também.
Grumdrig

Eu criei um minification otimizado (46 bytes menor) variante da sua implementação aqui: stackoverflow.com/a/52412162
Waruyama

Boa sorte já depurando esse @Waruyama. É para isso que serve o webpack!
Dylan Watson

61

Gerador de cadeia aleatória (Alfa-numé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"


Enquanto o descrito acima usa verificações adicionais para a saída A / N, A, N desejada , vamos detalhar os itens essenciais (somente alfa-numérico) para uma melhor compreensão:

  • Crie uma função que aceite um argumento (comprimento desejado do resultado aleatório de String)
  • Crie uma string vazia como var str = "";concatenar caracteres aleatórios
  • Dentro de um loop, crie um randnúmero de índice de 0 a 61 (0..9 + A..Z + a..z = 62)
  • Crie uma lógica condicional para ajustar / corrigirrand (já que é 0..61) incrementando-a em algum número (veja exemplos abaixo) para recuperar o CharCodenúmero certo e o caractere relacionado.
  • Dentro do loop concatenar a strumString.fromCharCode( incremented rand )

Vamos imaginar os intervalos da tabela 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 )dá um intervalo de 0..61(o que precisamos).
Vamos corrigir o aleatório para obter os intervalos corretos 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     |

A lógica de operação condicional da tabela acima:

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

A partir da explicação acima, eis o snippet 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"

Ou se você quiser:

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


33

A maneira mais simples é:

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

Isso gera seqüências aleatórias de 5 caracteres com base no horário atual. Saída de exemplo é 4mtxjou 4mv90ou4mwp1

O problema é que, se você chamá-lo duas vezes no mesmo segundo, ele gerará a mesma string.

A maneira mais segura é:

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

Isso gerará uma sequência aleatória de 4 ou 5 caracteres, sempre diferente. Saída de exemplo é como 30jzmou 1r591ou4su1a

Nos dois sentidos, a primeira parte gera um número aleatório. A .toString(36)peça converteu o número em uma representação base36 (alfadecimal) dela.


Não tenho muita certeza de como isso responde à pergunta; Esta é uma pergunta de 7 anos de idade com muitas respostas válidas já. Se você optar por fornecer uma nova resposta, tenha muito cuidado para garantir que sua resposta seja bem explicada e documentada.
Claies

1
Se você usa o Date, por que simplesmente não o usa como:(+new Date).toString(36)
seniorpreacher

Gosto da sua solução de números aleatórios, mas o 9e6 oferece apenas 9 milhões de possibilidades, além das 60,4 milhões de 5 dígitos (36 ^ 5), para que você possa substituí-lo por (0|Math.random()*6.04e7).toString(36)uma cobertura.
LeDroid

1
Eu queria uma sequência aleatória longa com uma rotina o mais curta possível (para uma demonstração de código) que não precise ser criptograficamente incrível, apenas produza um "buço" visual aleatório agradável. Eu gosto mais desta resposta (sua segunda), então obrigado. Meus dois centavos: eu posso vencê-lo por falta com menos um keystroke, e ele irá normalmente produzem 13 caracteres aleatórios (sem um período): (Math.random()*1e20).toString(36).
Andrew Willems 27/02

Um problema que tenho com esta resposta é que ele não usará [AZ], o que acontece na pergunta original.
user.friendly

22

Aqui estão alguns liners fáceis. mudançanew Array(5) para definir o comprimento.

Incluindo 0-9a-z

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

Incluindo 0-9a-zA-Z

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

20

Eu sei que todo mundo já entendeu direito, mas eu senti vontade de experimentar este da maneira mais leve possível (leve no código, não na 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));

Demora um pouco para entender, mas acho que realmente mostra o quão impressionante é a sintaxe do javascript.


20
Se você está tentando manter o código curto, por que escrever current = current ? current : '';quando pode escrever current = current || '';
CaffGeek

9
já que estamos falando micro otimização aqui eu realmente iria sugerir para ignorar a atribuição de variável por completo, se não for necessário:current || (current = '');
Thomas Heymann

Tentar a micro otimização ao usar um algoritmo recursivo "bom", mas que desperdiça recursos, não faz sentido :-) Um loop for ainda é melhor em Javascript e supera a recursão muito tempo, até que sejam feitos grandes avanços no código de otimização dos tempos de execução.
26419

17

Se você estiver usando Lodash ou Underscore , é muito simples:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');

6
Lodash usa_.sampleSize('asdfgh',5).join('')
marlo

2
Na verdade, essa não é uma boa solução, porque, por documentos, cada caractere é de um índice exclusivo. Isso significa que não é verdadeiramente aleatório, pois nenhum personagem pode / nunca se repetirá.
random_user_name 4/11

16

Para atender ao requisito [a-zA-Z0-9] e length = 5, use

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

Letras minúsculas, maiúsculas e números ocorrerão.


1
Eu acho que Math.random () pode levar a uma base64-string com poucos caracteres.
Leif

14

Caso alguém esteja interessado em uma linha (embora não esteja formatada como tal para sua conveniência) que aloque a memória de uma só vez (mas observe que, para pequenas cadeias de caracteres, isso realmente não importa), veja como fazê-lo:

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

Você pode substituir 5pelo comprimento da string que deseja. Obrigado a @AriyaHidayat neste post pela solução da mapfunção que não está funcionando no array esparso criado por Array(5).


13
Cada programa javascript é um 'one-liner' se você formatá-lo como tal
hacklikecrack

13

Aqui está o método que eu criei.
Ele criará uma sequência contendo caracteres maiúsculos e minúsculos.
Além disso, incluí a função que também criará uma sequência alfanumérica.

Exemplos de trabalho:
http://jsfiddle.net/greatbigmassive/vhsxs/ (somente 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;
}

Atualização julho de 2015
Isso faz a mesma coisa, mas faz mais sentido e inclui todas as 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)));
}

Com esta função, você nunca pode obter uma letra maiúscula maior que 'M' ou minúscula menor que 'n'.
precisa saber é o seguinte

Mesmo? ooh! provavelmente irá testá-lo mais então. Hmm, no entanto, dado que é uma sequência aleatória e nós realmente não nos importamos com o que as letras contêm (contanto que sejam aleatórias), ele ainda faz o que queremos que seja o que importa, mas sim, fornecerá um atualização, obrigado.
Adam

12

Supondo que você use underscorejs , é possível gerar elegantemente uma sequência aleatória em apenas duas linhas:

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');

6
Isso fará com que o valor retornado tenha todos os caracteres exclusivos. Além disso, o comprimento da string é limitado ao comprimento de var possível.
Yefu


10

Algoritmo rápido e aprimorado. Não garante uniforme (ver comentários).

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
Ótima resposta, mas a probabilidade não é uniforme. Existem 62 caracteres possíveis e crypto.getRandomValuesretorna um dos 256 valores exclusivos. Como 256 não é dividido por 62, você acaba tendo uma probabilidade um pouco maior de obter caracteres AH. Acho que a melhor solução é fazer o que o YouTube fez e apenas adicionar 2 caracteres adicionais (possivelmente -e _) ao conjunto de caracteres. De qualquer forma, grande trabalho - esta resposta precisa de muito mais amor :)
TeWu

adicionar - e _ é uma ótima idéia, pois você obterá o conjunto completo de base64 com base em URL seguro
cowbert

8

O problema com as respostas às perguntas "Preciso de seqüências aleatórias" (em qualquer idioma) é praticamente toda solução que utiliza uma especificação primária defeituosa do comprimento da string . As perguntas em si raramente revelam por que as strings aleatórias são necessárias, mas eu desafiaria que você raramente precise de strings aleatórias, digamos 8. O que você invariavelmente precisa é de um número de strings únicas , por exemplo, para usar como identificadores para algum propósito.

Existem duas maneiras principais de obter seqüências estritamente exclusivas : deterministicamente (o que não é aleatório) e armazenar / comparar (o que é oneroso). O que nós fazemos? Desistimos do fantasma. Em vez disso, optamos pela singularidade probabilística . Ou seja, aceitamos que haja algum risco (por menor que seja) que nossas cordas não sejam únicas. É aqui que se compreende a probabilidade de colisão e a entropia é útil.

Então, vou reformular a necessidade invariável, pois precisa de um certo número de strings com um pequeno risco de repetição. Como exemplo concreto, digamos que você queira gerar um potencial de 5 milhões de IDs. Você não deseja armazenar e comparar cada nova sequência e deseja que sejam aleatórias, portanto aceita alguns riscos de repetição. Como exemplo, digamos um risco de menos de 1 em um trilhão de chances de repetição. Então, qual o comprimento da corda que você precisa? Bem, essa pergunta é subespecificada, pois depende dos caracteres usados. Mais importante, porém, é equivocado. O que você precisa é de uma especificação da entropia das strings, não do seu comprimento. A entropia pode estar diretamente relacionada à probabilidade de repetição em algum número de strings. O comprimento da string não pode.

E é aqui que uma biblioteca como EntropyString pode ajudar. Para gerar IDs aleatórios com menos de 1 em um trilhão de chances de repetição em 5 milhões de strings 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-stringusa um conjunto de caracteres com 32 caracteres por padrão. Existem outros conjuntos de caracteres predefinidos e você também pode especificar seus próprios caracteres. Por exemplo, gerando IDs com a mesma entropia acima, mas usando caracteres hexadecimais:

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

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

const string = random.string(bits)

"27b33372ade513715481f"

Observe a diferença no comprimento da sequência devido à diferença no número total de caracteres no conjunto de caracteres usado. O risco de repetição no número especificado de sequências em potencial é o mesmo. Os comprimentos das strings não são. E o melhor de tudo, o risco de repetição e o número potencial de strings é explícito. Não há mais adivinhação com o comprimento da corda.


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

Isso é o mais limpo possível. Também é rápido, http://jsperf.com/ay-random-string .


Para mim, este sempre gera seqüências aleatórias com strLength - 1: - /
xanderiel

3
Mudando de --strLengthpara strLength--corrigi-lo para mim.
xanderiel

7

Você pode percorrer uma matriz de itens e adicioná-los recursivamente a uma variável de cadeia, por exemplo, se você quiser uma sequência aleatória de DNA:

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


6

Não encontrei uma solução limpa para suportar caracteres minúsculos e maiúsculos.

Suporte apenas em minúsculas:

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

Com base nessa solução para suportar letras minúsculas e maiúsculas:

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

Altere o 5in substr(2, 5)para ajustar o comprimento necessário.


6

Um forro:

Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil

Para torná-lo mais curto, altere o argumento Array(15)para um valor menor. Por exemplo: Array(4).
Andrew

Eu realmente amo essa solução, simples e clara. Ele está gerando 15 números aleatórios entre 0 e 1, gera o hexadecimal e remove os dois primeiros caracteres. Finalmente, está mesclando todos eles.
Siscia

5

Isso funciona com certeza

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

5

Que tal algo assim: Date.now().toString(36) não muito aleatório, mas curto e bastante único toda vez que você o chama.


1
Infelizmente, isso não será exclusivo, pois Date.now()possui apenas uma resolução de milissegundos. Quando executado em um loop simples, por exemplo, você recebe muitas duplicatas. for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }.
Nate

5

Caracteres alfanuméricos que não diferenciam maiúsculas de 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));

O benefício desta função é que você pode obter uma sequência aleatória de comprimento diferente e garantir o comprimento da sequência.

Todos os caracteres sensíveis a maiúsculas e 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


Esta resposta se encaixa mais no meu caso de uso. Seria legal se você pudesse adicionar um var possiblelike na resposta aceita, para que o resultado da função seja mais configurável.
Denis.Sabolotni

4

Gere uma sequência de 10 caracteres. O comprimento é definido pelo parâmetro (padrão 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;
}

4

Você pode usar coderain . É uma biblioteca para gerar códigos aleatórios de acordo com o padrão fornecido. Use #como um espaço reservado para caracteres maiúsculos e minúsculos, além de dígitos:

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

Existem outros espaços reservados, como Apara letras maiúsculas ou 9dígitos.

O que pode ser útil é que chamar .next() sempre fornecerá um resultado exclusivo para que você não precise se preocupar com duplicatas.

Aqui está um aplicativo de demonstração que gera uma lista de códigos aleatórios exclusivos .

Divulgação completa: sou o autor da coderain.


NÃO NÃO NÃO - use métodos nativos.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.