I want a 5 character string composed of characters picked randomly from the set [azAZ09]
.
What's the best way to do this with JavaScript?
truerandom
result! They are only pseudorandom
. When using random strings for protection or security, don't use any of them!!! Try one of these api's: random.org  anyone I think this will work for you:
function makeid(length) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
let counter = 0;
while (counter < length) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
counter += 1;
}
return result;
}
console.log(makeid(5));
Answered 20230920 20:24:59
floor
is unneeded: for(var text=''; text.length < 5;) text += possible.charAt(Math.random() * possible.length)  anyone +=
is often faster for some reason, even used inside loops  jsperf.com/joinvsconcatenation  anyone crypto
instead.  anyone //Can change 7 to 2 for longer results.
let r = (Math.random() + 1).toString(36).substring(7);
console.log("random", r);
Note: The above algorithm has the following weaknesses:
Math.random()
may produce predictable ("randomlooking" but not really random) output depending on the implementation. The resulting string is not suitable when you need to guarantee uniqueness or unpredictability.Answered 20230920 20:24:59
Math.random().toString(36).substr(2, 5)
, because .substring(7)
causes it to be longer than 5 characters. Full points, still!  anyone toString
method of a number type in javascript takes an optional parameter to convert the number into a given base. If you pass two, for example, you'll see your number represented in binary. Similar to hex (base 16), base 36 uses letters to represent digits beyond 9. By converting a random number to base 36, you'll wind up with a bunch of seemingly random letters and numbers.  anyone (Math.random() + 1).toString(36).substring(7);
 anyone substring(7)
takes the digits from the least significant part of the base36 string. toString(36)
appears to convert the random number to a 16 digit base36 string, but the precision required for this would be 36^16 = 7.958e24 possible numbers, where the precision of Math.random() is only 4.5e15. Taking the digits from most significant end with .slice(2,5)
solves this: 5 digit example  anyone Math.random is bad for this kind of thing
server side
Use node crypto module 
var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');
// "bb5dc8842ca31d4603d6aa11448d1654"
The resulting string will be twice as long as the random bytes you generate; each byte encoded to hex is 2 characters. 20 bytes will be 40 characters of hex.
client side
Use the browser's crypto module, 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).
// dec2hex :: Integer > String
// i.e. 0255 > '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"
A stepbystep console example 
> var arr = new Uint8Array(4) # make array of 4 bytes (values 0255)
> 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 ]
For IE11 support you can use 
(window.crypto  window.msCrypto).getRandomValues(arr)
For browser coverage see https://caniuse.com/#feat=getrandomvalues
client side (old browsers)
If you must support old browsers, consider something like uuid

const uuid = require("uuid");
const id = uuid.v4();
// "110ec58aa0f24ac48393c866d813b8d1"
Answered 20230920 20:24:59
.map()
in Option 3. Array.from(arr, dec2hex).join('')
=== Array.from(arr).map(dec2hex).join('')
. Thanks for introducing me to these features :)  anyone dec2hex
was provided an example encoder. It's up to you to represent the bytes however you choose. I updated the post with your suggestion.  anyone Returns exactly 5 random characters, as opposed to some of the top rated answers found here.
Math.random().toString(36).slice(2, 7);
Answered 20230920 20:24:59
Math.random().toString(36)
returns a number with less than 5 characters?  anyone Math.random
not returning 0. Hope you never have to debug this event  anyone Here's an improvement on doubletap's excellent answer. The original has two drawbacks which are addressed here:
First, as others have mentioned, it has a small probability of producing short strings or even an empty string (if the random number is 0), which may break your application. Here is a solution:
(Math.random().toString(36)+'00000000000000000').slice(2, N+2)
Second, both the original and the solution above limit the string size N to 16 characters. The following will return a string of size N for any N (but note that using N > 16 will not increase the randomness or decrease the probability of collisions):
Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)
Explanation:
Further thoughts:
Update:
Here are a couple other functionalstyle oneliners I came up with. They differ from the solution above in that:
So, say your alphabet of choice is
var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Then these two are equivalent to each other, so you can pick whichever is more intuitive to you:
Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
and
Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
Edit:
I seems like qubyte and Martijn de Milliano came up with solutions similar to the latter (kudos!), which I somehow missed. Since they don't look as short at a glance, I'll leave it here anyway in case someone really wants a oneliner :)
Also, replaced 'new Array' with 'Array' in all solutions to shave off a few more bytes.
Answered 20230920 20:24:59
(Math.random()+1).toString(36).substring(7);
 anyone Math.random().toString(36).substring(2,7)
gives an expected result which is more like the .substring(2, n+2)
 anyone Array.apply(null, {length: 5}).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('')
 anyone The most compact solution, because slice
is shorter than substring
. Subtracting from the end of the string allows to avoid floating point symbol generated by the random
function:
Math.random().toString(36).slice(5);
or even
(+new Date).toString(36).slice(5);
Update: Added one more approach using btoa
method:
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));
Answered 20230920 20:24:59
Math.random().toString(36).slice(5);
 What if Math.random()
returns 0.0
?  anyone "0"
;)  anyone Math.random()
returns 0.5
the result is "0.i"
. Not sure if there are other edge cases. Just wanted to point out that this is not a correct answer to the question (5 characters from [azAZ09]).  anyone (+new Date + Math.random())
to prevent this case. Anyway, thanks for the note.  anyone bota
at all? I commented on other answers but using this test case you can see you going to use only 14 chars out of 64 that base64 has to offer: [...new Set([...Array(100000)].map(()=>btoa(Math.random()).substr(0, 5)).join(""))].sort()
 anyone A newer version with es6 spread operator:
[...Array(30)].map(() => Math.random().toString(36)[2]).join('')
30
is an arbitrary number, you can pick any token length you want36
is the maximum radix number you can pass to numeric.toString(), which means all numbers and az lowercase letters2
is used to pick the 3rd index from the random string which looks like this: "0.mfbiohx64i"
, we could take any index after 0.
Answered 20230920 20:24:59
 '0'
so that it falls back to 0
instead of undefined
if Math.random()
returns 0
(it never returns 1
)  anyone Something like this should work
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;
}
Call with default charset [azAZ09] or send in your own:
var randomValue = randomString(5);
var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');
Answered 20230920 20:24:59
len
directly in a while
loop  anyone crypto.randomBytes(3).toString('hex')
(3 bytes gives 6 chars, for example)  anyone function randomstring(L) {
var s = '';
var randomchar = function() {
var n = Math.floor(Math.random() * 62);
if (n < 10) return n; //110
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));
Answered 20230920 20:24:59
while(s.length< L) s+= randomchar();
 anyone while(L)
will do it  anyone 'A'.charCodeAt(0)
rather than the magic number 55
(and likewise for the 61
). Particularly since, on my platform anyway, the magic number that returns is 65
. That code will selfdocument better as well.  anyone /**
* Pseudorandom string generator
* http://stackoverflow.com/a/27872144/383904
* Default: return a random alphanumeric 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"
While the above uses additional checks for the desired A/N, A, N output, let's break it down the to the essentials (AlphaNumeric only) for a better understanding:
var str = "";
to concatenate random charactersrand
index number from 0 to 61 (0..9+A..Z+a..z = 62)rand
(since it's 0..61) incrementing it by some number (see examples below) to get back the right CharCode
number and the related Character.str
a String.fromCharCode( incremented rand )
Let's picture the ASCII Character table ranges:
_____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 )
gives a range from 0..61
(what we need).
Let's fix the random to get the correct charCode ranges:
 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 /* 9035 = 55 */ = 65..90 
a..z  36..61  97..122  rand += 61 /* 12261 = 61 */ = 97..122 
The conditional operation logic from the table above:
rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ;
// rand += true ? ( true ? 55 else 61 ) else 48 ;
From the explanation above, here's the resulting alphanumeric snippet:
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"
Or if you will:
const randomString = (n, r='') => {
while (n) r += String.fromCharCode((r=Math.random()*620, r+=r>9?(r<36?55:61):48));
return r;
};
console.log(randomString(10))
Answered 20230920 20:24:59
x.toString(36)
 as is used in the above answers  was not reliably generating the same characters when I compared the outputs of two apps that had different ES versions, and this function fixed this for me as it does not use .toString()
!  anyone To meet requirement [azAZ09] and length of 5 characters, use
For Browser:
btoa(Math.random().toString()).substring(10,15);
For NodeJS:
Buffer.from(Math.random().toString()).toString("base64").substring(10,15);
Lowercase letters, uppercase letters, and numbers will occur.
(it's typescript compatible)
Answered 20230920 20:24:59
Set
it to see unique chars and then sort. one liner for that: [...new Set([...Array(100000)].map(()=>btoa(Math.random()).substr(5, 5)).join(""))].sort()
 anyone toString
in the browser example?  anyone toString()
. But as I wanted to do something as "it's typescript compatible". So I left it that way.  anyone The simplest way is:
(new Date%9e6).toString(36)
This generate random strings of 5 characters based on the current time. Example output is 4mtxj
or 4mv90
or 4mwp1
The problem with this is that if you call it two times on the same second, it will generate the same string.
The safer way is:
(0Math.random()*9e6).toString(36)
This will generate a random string of 4 or 5 characters, always diferent. Example output is like 30jzm
or 1r591
or 4su1a
In both ways the first part generate a random number. The .toString(36)
part cast the number to a base36 (alphadecimal) representation of it.
Answered 20230920 20:24:59
(+new Date).toString(36)
 anyone (Math.random()*1e20).toString(36)
.  anyone Here are some easy one liners. Change new Array(5)
to set the length.
09az
new Array(5).join().replace(/(.$)/g, function(){return ((Math.random()*36)0).toString(36);})
09azAZ
new Array(5).join().replace(/(.$)/g, function(){return ((Math.random()*36)0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();});
09az
)Array(5).fill().map(n=>(Math.random()*360).toString(36)).join('')
Answered 20230920 20:24:59
I know everyone has got it right already, but i felt like having a go at this one in the most lightweight way possible(light on code, not 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));
It takes a bit of time to wrap your head around, but I think it really shows how awesome javascript's syntax is.
Answered 20230920 20:24:59
current = current ? current : '';
when you can write current = current  ''
;  anyone current  (current = '');
 anyone There is no best way to do this. You can do it any way you prefer, as long as the result suits your requirements. To illustrate, I've created many different examples, all which should provide the same endresult
Most other answers on this page ignore the uppercase character requirement.
Here is my fastest solution and most readable. It basically does the same as the accepted solution, except it is a bit faster.
function readableRandomStringMaker(length) {
for (var s=''; s.length < length; s += 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.charAt(Math.random()*620));
return s;
}
console.log(readableRandomStringMaker(length));
// e3cbN
Here is a compact, recursive version which is much less readable:
const compactRandomStringMaker = (length) => length && "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*620) + (compactRandomStringMaker(length)"");
console.log(compactRandomStringMaker(5));
// DVudj
A more compact oneliner:
Array(5).fill().map(()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62)).join("")
// 12oEZ
A variation of the above:
" ".replaceAll(" ",()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62))
The most compact oneliner, but inefficient and unreadable  it adds random characters and removes illegal characters until length is l:
((l,f=(p='')=>p.length<l?f(p+String.fromCharCode(Math.random()*123).replace(/[^az09]/i,'')):p)=>f())(5)
A cryptographically secure version, which is wasting entropy for compactness, and is a waste regardless because the generated string is so short:
[...crypto.getRandomValues(new Uint8Array(999))].map((c)=>String.fromCharCode(c).replace(/[^az09]/i,'')).join("").substr(0,5)
// 8fzPq
Or, without the lengthargument it is even shorter:
((f=(p='')=>p.length<5?f(p+String.fromCharCode(Math.random()*123).replace(/[^az09]/i,'')):p)=>f())()
// EV6c9
Then a bit more challenging  using a nameless recursive arrow function:
((l,s=((l)=>l&&"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*620)+(s(l)""))) => s(l))(5);
// qzal4
This is a "magic" variable which provides a random character every time you access it:
const c = new class { [Symbol.toPrimitive]() { return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*620) } };
console.log(c+c+c+c+c);
// AgMnz
A simpler variant of the above:
const c=()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*620);
c()+c()+c()+c()+c();
// 6Qadw
Answered 20230920 20:24:59
Generate a secure random alphanumeric Base62
string:
function generateUID(length)
{
return window.btoa(String.fromCharCode(...window.crypto.getRandomValues(new Uint8Array(length * 2)))).replace(/[+/]/g, "").substring(0, length);
}
console.log(generateUID(22)); // "yFg3Upv2cE9cKOXd7hHwWp"
console.log(generateUID(5)); // "YQGzP"
Answered 20230920 20:24:59
In case anyone is interested in a oneliner (although not formatted as such for your convenience) that allocates the memory at once (but note that for small strings it really does not matter) here is how to do it:
Array.apply(0, Array(5)).map(function() {
return (function(charset){
return charset.charAt(Math.floor(Math.random() * charset.length))
}('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));
}).join('')
You can replace 5
by the length of the string you want. Thanks to @AriyaHidayat in this post for the solution to the map
function not working on the sparse array created by Array(5)
.
Answered 20230920 20:24:59
If you are using Lodash or Underscore, then it so simple:
var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
Answered 20230920 20:24:59
_.sampleSize('asdfgh',5).join('')
 anyone const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
Answered 20230920 20:24:59
Here's the method I created.
It will create a string containing both uppercase and lowercase characters.
In addition I've included the function that will created an alphanumeric string too.
Working examples:
http://jsfiddle.net/greatbigmassive/vhsxs/ (alpha only)
http://jsfiddle.net/greatbigmassive/PJwg8/ (alphanumeric)
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;
}
Upgrade July 2015
This does the same thing but makes more sense and includes all letters.
var s = "";
while(s.length<x&&x>0){
v = Math.random()<0.5?32:0;
s += String.fromCharCode(Math.round(Math.random()*((122v)(97v))+(97v)));
}
Answered 20230920 20:24:59
One liner:
Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
Answered 20230920 20:24:59
Array(15)
to a smaller value. E.g.: Array(4)
.  anyone Improved @Andrew's answer above :
Array.from({ length : 1 }, () => Math.random().toString(36)[2]).join('');
Base 36 conversion of the random number is inconsistent, so selecting a single indice fixes that. You can change the length for a string with the exact length desired.
Answered 20230920 20:24:59
Assuming you use underscorejs it's possible to elegantly generate random string in just two lines:
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
Answered 20230920 20:24:59
function randomString (strLength, charSet) {
var result = [];
strLength = strLength  5;
charSet = charSet  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
while (strLength) { // (note, fixed typo)
result.push(charSet.charAt(Math.floor(Math.random() * charSet.length)));
}
return result.join('');
}
This is as clean as it will get. It is fast too, http://jsperf.com/ayrandomstring.
Answered 20230920 20:24:59
strLength  1
:/  anyone strLength
to strLength
fixes it for me.  anyone strLength
postfix, not prefix.  anyone Fast and improved algorithm. Does not guarantee uniform (see comments).
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;
}
Answered 20230920 20:24:59
crypto.getRandomValues
returns one of 256 unique values. Because 256 is not divided by 62, you end up having slightly higher probability of getting characters AH. I think the best solution is to do what YouTube did, and just add 2 additional characters (possibly 
and _
) to the charset. Anyway, great work  this answer needs so much more love :)  anyone How about this compact little trick?
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('');
You need the Array.apply
there to trick the empty array into being an array of undefineds.
If you're coding for ES2015, then building the array is a little simpler:
var randomString = Array.from({ length: stringLength }, pickRandom).join('');
Answered 20230920 20:24:59
You can loop through an array of items and recursively add them to a string variable, for instance if you wanted a random DNA sequence:
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));
Answered 20230920 20:24:59
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));
The benefit of this function is that you can get different length random string and it ensures the length of the string.
function randStr(len) {
let s = '';
while (len) s += String.fromCodePoint(Math.floor(Math.random() * (126  33) + 33));
return s;
}
// usage
console.log(randStr(50));
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
Answered 20230920 20:24:59
var possible
like in the accepted answer, so the outcome of the function is more configurable.  anyone The problem with responses to "I need random strings" questions (in whatever language) is practically every solution uses a flawed primary specification of string length. The questions themselves rarely reveal why the random strings are needed, but I would challenge you rarely need random strings of length, say 8. What you invariably need is some number of unique strings, for example, to use as identifiers for some purpose.
There are two leading ways to get strictly unique strings: deterministically (which is not random) and store/compare (which is onerous). What do we do? We give up the ghost. We go with probabilistic uniqueness instead. That is, we accept that there is some (however small) risk that our strings won't be unique. This is where understanding collision probability and entropy are helpful.
So I'll rephrase the invariable need as needing some number of strings with a small risk of repeat. As a concrete example, let's say you want to generate a potential of 5 million IDs. You don't want to store and compare each new string, and you want them to be random, so you accept some risk of repeat. As example, let's say a risk of less than 1 in a trillion chance of repeat. So what length of string do you need? Well, that question is underspecified as it depends on the characters used. But more importantly, it's misguided. What you need is a specification of the entropy of the strings, not their length. Entropy can be directly related to the probability of a repeat in some number of strings. String length can't.
And this is where a library like EntropyString can help. To generate random IDs that have less than 1 in a trillion chance of repeat in 5 million strings using entropystring
:
import {Random, Entropy} from 'entropystring'
const random = new Random()
const bits = Entropy.bits(5e6, 1e12)
const string = random.string(bits)
"44hTNghjNHGGRHqH9"
entropystring
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 './entropystring'
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.
Answered 20230920 20:24:59
nanoid
is much more popular than entropystring
and seems just as good for my purposes.  anyone Whilst this answer is almost similar to others, it differs in that it uses:
repeat
to create 5 characters (can be generalized to n
)repeat
with regex /./g
to replace those 5 characterslet ans = "x".repeat(5)
.replace(/./g, c => "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[Math.floor(Math.random() * 62) ] );
console.log(ans);
Answered 20230920 20:24:59