Genera string / caratteri casuali in JavaScript

Voglio una stringa di 5 caratteri composta da caratteri scelti casualmente dal set [a-zA-Z0-9] .

Qual è il modo migliore per farlo con JavaScript?

Penso che questo funzionerà per te:

 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()); 
 let r = Math.random().toString(36).substring(7); console.log("random", r); 

Math.random è male per questo genere di cose

opzione 1

Se sei in grado di fare questo lato server , usa semplicemente il modulo crypto

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

La stringa risultante sarà lunga il doppio dei byte casuali generati; ogni byte codificato in esadecimale è di 2 caratteri. 20 byte saranno 40 caratteri di esagono.


opzione 2

Se devi fare questo lato client , magari prova il modulo uuid

 var uuid = require("uuid"); var id = uuid.v4(); // "110ec58a-a0f2-4ac4-8393-c866d813b8d1" 

Opzione 3

Se devi fare questo lato client e non devi supportare i vecchi browser, puoi farlo senza dipendenze

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

Ecco un miglioramento nell’eccellente risposta di doubletap . L’originale ha due inconvenienti che vengono affrontati qui:

Innanzitutto, come altri hanno menzionato, ha una piccola probabilità di produrre stringhe brevi o anche una stringa vuota (se il numero casuale è 0), che potrebbe violare la vostra applicazione. Ecco una soluzione:

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

In secondo luogo, sia l’originale che la soluzione sopra limitano la stringa da N a 16 caratteri. Quanto segue restituirà una stringa di dimensione N per ogni N (ma si noti che l’utilizzo di N> 16 non aumenterà la casualità o diminuirà la probabilità di collisioni):

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

Spiegazione:

  1. Scegli un numero casuale nell’intervallo [0,1), cioè tra 0 (incluso) e 1 (esclusivo).
  2. Converti il ​​numero in una stringa base-36, cioè usando i caratteri 0-9 e az.
  3. Pad con zeri (risolve il primo problema).
  4. Taglia la parte iniziale “0”. prefisso e zeri extra di riempimento.
  5. Ripeti la stringa abbastanza volte per avere almeno N caratteri al suo interno (unendo stringhe vuote con la stringa casuale più breve usata come delimitatore).
  6. Taglia esattamente N caratteri dalla stringa.

Ulteriori pensieri:

  • Questa soluzione non utilizza lettere maiuscole, ma in quasi tutti i casi (non è previsto il gioco di parole) non importa.
  • La lunghezza massima della stringa in corrispondenza di N = 16 nella risposta originale viene misurata in Chrome. In Firefox è N = 11. Ma come spiegato, la seconda soluzione riguarda il supporto di qualsiasi lunghezza di stringa richiesta, non l’aggiunta di casualità, quindi non fa molta differenza.
  • Tutte le stringhe restituite hanno la stessa probabilità di essere restituite, almeno per quanto i risultati restituiti da Math.random () sono equamente distribuiti (questa non è la casualità della forza crittografica, in ogni caso).
  • Non tutte le stringhe possibili di taglia N possono essere restituite. Nella seconda soluzione ciò è ovvio (poiché la stringa più piccola viene semplicemente duplicata), ma anche nella risposta originale questo è vero poiché nella conversione in base-36 gli ultimi bit potrebbero non essere parte dei bit casuali originali. In particolare, se si guarda il risultato di Math.random (). ToString (36), si noterà che l’ultimo carattere non è distribuito uniformsmente. Di nuovo, in quasi tutti i casi non importa, ma dividiamo la stringa finale dall’inizio piuttosto che alla fine della stringa casuale in modo che le stringhe corte (ad es. N = 1) non siano influenzate.

Aggiornare:

Ecco un paio di altri one-liner in stile funzionale che mi sono venuti in mente. Si differenziano dalla soluzione di cui sopra in quanto:

  • Usano un alfabeto arbitrario esplicito (più generico e adatto alla domanda originale che richiede lettere maiuscole e minuscole).
  • Tutte le stringhe di lunghezza N hanno uguale probabilità di essere restituite (cioè le stringhe non contengono ripetizioni).
  • Si basano su una funzione mappa, piuttosto che sul trucco toString (36), che li rende più semplici e facili da capire.

Quindi, diciamo che il tuo alfabeto di scelta è

 var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 

Quindi questi due sono equivalenti tra loro, quindi puoi scegliere quello che ti è più intuitivo:

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

Modificare:

Mi sembra che Quiete e Martijn de Milliano abbiano trovato soluzioni simili a quest’ultima (complimenti!), Che in qualche modo mi mancavano. Dal momento che non hanno l’aspetto più breve, lo lascerò qui comunque nel caso in cui qualcuno voglia davvero un one-liner 🙂

Inoltre, ha sostituito ‘nuovo array’ con ‘Array’ in tutte le soluzioni per eliminare alcuni byte in più.

Breve, facile e affidabile

Restituisce esattamente 5 caratteri casuali, al contrario di alcune delle risposte più votate trovate qui.

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

Qualcosa del genere dovrebbe funzionare

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

Chiama con il set di caratteri predefinito [a-zA-Z0-9] o invia il tuo:

 var randomValue = randomString(5); var randomValue = randomString(5, 'PICKCHARSFROMTHISSET'); 
 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); //AZ return String.fromCharCode(n + 61); //az } while (s.length < L) s += randomchar(); return s; } console.log(randomstring(5)); 

La soluzione più compatta, perché slice è più corta della substring . La sottrazione dalla fine della stringa consente di evitare il simbolo del punto mobile generato da una funzione random :

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

o anche

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

Generatore casuale di stringhe (alfa-numerico | alfa | numerico)

 /** * RANDOM STRING GENERATOR * * Info: http://stackoverflow.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 aZ 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++9?r<36?55:61:48); } return str; } 
 randomString(10); // "4Z8iNQag9v" randomString(10, "A"); // "aUkZuHNcWw" randomString(10, "N"); // "9055739230" 

Divertiti. demo di jsBin


Mentre quanto sopra utilizza controlli aggiuntivi per l'output desiderato (A / N, A, N), scomporlo fino all'essenziale (solo alfa-numerico) per una migliore comprensione:

  • Crea una funzione che accetta un argomento (lunghezza desiderata del risultato casuale della stringa)
  • Crea una stringa vuota come var str = ""; concatenare caratteri casuali
  • All'interno di un loop creare un numero di indice di Rand da 0 a 61 (0..9 + A..Z + a..z = 62)
  • Crea una logica condizionale per regolare / correggere rand (poiché è 0..61) incrementandola di un certo numero (vedi esempi sotto) per ottenere il giusto numero di CharCode e il relativo Carattere.
  • All'interno del ciclo concatenare con str a String.fromCharCode( incremented rand )

Vediamo la tabella caratteri e i loro intervalli :

 _____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 ) fornisce un intervallo da 0..61 (ciò di cui abbiamo bisogno). Come correggere (incrementare) il random per ottenere gli intervalli di charCode corretti?

  | 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 logica dell'operazione condizionale dalla tabella sopra:

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

Se hai seguito la spiegazione di cui sopra dovresti essere in grado di creare questo frammento alfanumerico :

demo di jsBin

 function randomString( len ) { var str = ""; // String result for(var i=0; i9? (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" 

O se vuoi:

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

Il modo più semplice è:

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

Questo genera stringhe casuali di 5 caratteri in base al tempo corrente. L’output di esempio è 4mtxj o 4mv90 o 4mwp1

Il problema con questo è che se lo chiami due volte sullo stesso secondo, genererà la stessa stringa.

Il modo più sicuro è:

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

Questo genererà una stringa casuale di 4 o 5 caratteri, sempre diversa. L’output di esempio è come 30jzm o 1r591 o 4su1a

In entrambi i modi, la prima parte genera un numero casuale. La parte .toString(36) il numero in una rappresentazione base36 (alfa- decimale) di esso.

Una versione più recente con operatore di diffusione es6 :

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

  • Il 30 è un numero arbitrario, puoi scegliere qualsiasi lunghezza di token che desideri
  • Il 36 è il numero massimo della radice che puoi passare a numeric.toString () , che significa tutti i numeri e le lettere minuscole az
  • Il 3 è usato per scegliere il terzo numero dalla stringa casuale che assomiglia a questo: "0.mfbiohx64i" , potremmo prendere qualsiasi indice dopo 0.

Ecco alcuni semplici rivestimenti. Cambia la new Array(5) per impostare la lunghezza.

Compreso 0-9a-z

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

Compreso 0-9a-zA-Z

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

Se stai usando Lodash o Underscore , allora è così semplice:

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

So che tutti hanno già capito bene, ma mi è sembrato di provare a farlo nel modo più leggero ansible (luce sul codice, non sulla 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)); 

Supponendo che tu usi underscorejs è ansible generare elegantemente una stringa casuale in sole due righe:

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

Ecco il metodo che ho creato.
Creerà una stringa contenente caratteri maiuscoli e minuscoli.
Inoltre ho incluso la funzione che creerà anche una stringa alfanumerica.

Esempi di lavoro:
http://jsfiddle.net/greatbigmassive/vhsxs/ (solo alpha)
http://jsfiddle.net/greatbigmassive/PJwg8/ (alfanumerico)

 function randString(x){ var s = ""; while(s.length0){ var r = Math.random(); s+= String.fromCharCode(Math.floor(r*26) + (r>0.5?97:65)); } return s; } 

Aggiornamento luglio 2015
Questo fa la stessa cosa ma ha più senso e include tutte le lettere.

 var s = ""; while(s.length0){ v = Math.random()<0.5?32:0; s += String.fromCharCode(Math.round(Math.random()*((122-v)-(97-v))+(97-v))); } 

Nel caso in cui qualcuno sia interessato a un one-liner (anche se non formattato come tale per comodità dell’utente) che alloca la memoria in una volta (ma si noti che per le stringhe piccole non importa davvero) ecco come farlo:

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

Puoi sostituire 5 base alla lunghezza della stringa che desideri. Grazie a @AriyaHidayat in questo post per la soluzione della funzione map non funziona sull’array sparse creato da Array(5) .

Per soddisfare i requisiti [a-zA-Z0-9] e lunghezza = 5 utilizzare

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

Verranno visualizzate lettere minuscole, lettere maiuscole e numeri.

Algoritmo veloce e migliorato. Non garantisce uniformità (vedi commenti).

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

Questo è pulito come otterrà. È anche veloce, http://jsperf.com/ay-random-string .

È ansible eseguire il ciclo di una serie di elementi e aggiungerli in modo ricorsivo a una variabile stringa, ad esempio se si desidera una sequenza casuale di 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)); 

Non ho trovato una soluzione pulita per supportare caratteri minuscoli e maiuscoli.

Supporto solo in lettere minuscole:

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

Basandosi su questa soluzione per supportare lettere minuscole e maiuscole:

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

Cambia il 5 in substr(2, 5) per adattarlo alla lunghezza che ti serve.

Questo funziona di sicuro

  

Genera una stringa di 10 caratteri. La lunghezza è impostata dal parametro (valore predefinito 10).

 function random_string_generator(len) { var len = len || 10; var str = ''; var i = 0; for(i=0; i 

Ecco uno script di test per la risposta n. 1 (grazie @ csharptest.net)

lo script esegue makeid() 1 million volte e come puoi vedere 5 non è un caso unico. eseguirlo con una lunghezza char di 10 è abbastanza affidabile. L’ho eseguito circa 50 volte e non ho ancora visto un duplicato :-)

nota: il limite di dimensioni dello stack del nodo supera i 4 milioni circa, quindi non è ansible eseguire questo 5 milioni di volte in cui non terminerà mai.

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

Puoi usare coderain . È una libreria per generare codici casuali secondo un determinato modello. Usa # come segnaposto per caratteri maiuscoli e minuscoli e anche per cifre:

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

Ci sono altri segnaposto come A per le lettere maiuscole o 9 per le cifre.

Quello che può essere utile è che chiamare .next() ti darà sempre un risultato unico in modo da non .next() preoccupare dei duplicati.

Ecco un’applicazione demo che genera un elenco di codici casuali univoci .

Piena divulgazione: sono l’autore del coderain.

Che ne dici di questo piccolo trucco compatto?

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

È necessario l’ Array.apply lì per ingannare l’array vuoto in una serie di indefiniti.

Se stai codificando per ES2015, la costruzione dell’array è un po ‘più semplice:

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

Il problema con le risposte alle domande “Ho bisogno di stringhe casuali” (in qualsiasi lingua) è praticamente ogni soluzione utilizza una specifica imperfetta della lunghezza della stringa . Le domande stesse raramente rivelano il motivo per cui sono necessarie le stringhe casuali, ma vorrei sfidare raramente stringhe casuali di lunghezza, ad esempio 8. Ciò che è invariabilmente necessario è un certo numero di stringhe univoche , ad esempio, da utilizzare come identificatori per qualche scopo.

Esistono due modi principali per ottenere stringhe strettamente univoche : deterministicamente (che non è casuale) e memorizza / confronta (che è oneroso). Cosa facciamo? Abbandoniamo il fantasma. Invece andiamo con unicità probabilistica . Cioè, accettiamo che c’è un rischio (per quanto piccolo) che le nostre stringhe non siano uniche. Qui è utile comprendere la probabilità di collisione e l’ entropia .

Quindi riformulerò il bisogno invariabile come se avessi bisogno di un certo numero di stringhe con un piccolo rischio di ripetizione. Come esempio concreto, supponiamo di voler generare un potenziale di 5 milioni di ID. Non vuoi memorizzare e confrontare ogni nuova stringa e vuoi che siano casuali, quindi accetti il ​​rischio di ripetizione. Ad esempio, diciamo un rischio inferiore a 1 su un trilione di possibilità di ripetizione. Quindi che lunghezza di corda hai bisogno? Bene, questa domanda è sottosprecisa in quanto dipende dai caratteri usati. Ma ancora più importante, è fuorviante. Quello di cui hai bisogno è una specifica dell’entropia delle stringhe, non della loro lunghezza. L’entropia può essere direttamente correlata alla probabilità di una ripetizione in un certo numero di stringhe. La lunghezza della stringa non può.

Ed è qui che una libreria come EntropyString può aiutare. To generate random IDs that have less than 1 in a trillion chance of repeat in 5 million strings using 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 uses a character set with 32 characters by default. There are other predefined characters sets, and you can specify your own characters as well. For example, generating IDs with the same entropy as above but using hex characters:

 import {Random, Entropy, charSet16} from './entropy-string' const random = new Random(charSet16) const bits = Entropy.bits(5e6, 1e12) const string = random.string(bits) 

“27b33372ade513715481f”

Note the difference in string length due to the difference in total number of characters in the character set used. The risk of repeat in the specified number of potential strings is the same. The string lengths are not. And best of all, the risk of repeat and the potential number of strings is explicit. No more guessing with string length.

How about something like this: Date.now().toString(36) Not very random, but short and quite unique every time you call it.

Expanding on Doubletap’s elegant example by answering the issues Gertas and Dragon brought up. Simply add in a while loop to test for those rare null circumstances, and limit the characters to five.

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

Here’s a jsfiddle alerting you with a result: http://jsfiddle.net/pLJJ7/