Skip to content

Instantly share code, notes, and snippets.

@6174
Created July 23, 2013 13:36
Show Gist options
  • Save 6174/6062387 to your computer and use it in GitHub Desktop.
Save 6174/6062387 to your computer and use it in GitHub Desktop.
Generate a random string in JavaScript In a short and fast way!
//http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
@nonara
Copy link

nonara commented Sep 9, 2019

Here's a little different spin.

  • Sets are attached to function (rnd.num, rnd,alphaLower, etc.)
  • Sequential sets are generated using fromCharCode
  • Uses generator function
  • Uses rest params for sets - ie rnd([length], [set1], [set2], ...)

See examples for use

const rnd = (() => {
    const gen = (min, max) => max++ && [...Array(max-min)].map((s, i) => String.fromCharCode(min+i));

    const sets = {
        num: gen(48,57),
        alphaLower: gen(97,122),
        alphaUpper: gen(65,90),
        special: [...`~!@#$%^&*()_+-=[]\{}|;:'",./<>?`]
    };

    function* iter(len, set) {
        if (set.length < 1) set = Object.values(sets).flat(); 
        for (let i = 0; i < len; i++) yield set[Math.random() * set.length|0]
    }

    return Object.assign(((len, ...set) => [...iter(len, set.flat())].join('')), sets);
})();


console.log('OUTPUT: ', rnd(20));    // Use all sets
// OUTPUT:  Kr8K1,f5hQa;YJC~7K9z

console.log('OUTPUT: ', rnd(20, rnd.alphaLower));
// OUTPUT:  cpjbkwvslxsofzvkekcw

console.log('OUTPUT: ', rnd(20, rnd.alphaUpper rnd.special));
// OUTPUT:  S]|-X]=N}TZC,GE;=,.D

@karfau
Copy link

karfau commented Oct 27, 2019

keep in mind that Math.random can also return 0 and that some conversions using .toString(n) might be much shorter that the number of chars you expect according to the second argument of substr/substring: https://jsfiddle.net/karfau/5632zu84/27/

@GottZ
Copy link

GottZ commented Oct 28, 2019

hey there. just want you to let this sink in for a moment:
https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#Examples

just for the lulz i made this:

public domain:

const random = (function() {
  const buffer = new Uint8Array(32);
  let index;
  let bitIndex;
  const max = BigInt(buffer.length);

  const reset = function() {
    index = 0n;
    bitIndex = 0n;
    crypto.getRandomValues(buffer);
  };
  reset();

  const getBits = function(count) {
    let bits = 0n;
    while (count > 0n) {
      const todo = count < 8n - bitIndex ? count : 8n - bitIndex;
      count -= todo;
      bits = bits << todo;
      bits += (BigInt(buffer[index]) >> bitIndex) & ((1n << todo) -1n);
      bitIndex += todo;
      if (bitIndex === 8n) {
        bitIndex = 0n;
        index++;
      }
      if (index === max) {
        reset();
      }
    }
    return bits;
  };

  const countBits = function(num) {
    let bitCount = 0n;
    while (num > 0n) {
      bitCount++;
      num = num >> 1n;
    }
    return bitCount;
  };

  const getN = function(max, bitCount) {
    if (max <= 0n) {
      throw new Error("this does not compute unless you want an infinite loop");
    }
    let out;

    do {
      out = getBits(bitCount);
    } while (out >= max);

    return out;
  };

  return function(input, count) {
    let wasNumber = false;
    let wasString = false;

    switch (typeof input) {
      default: {
        throw new Error("unsupported input");
      }
      case "number": {
        wasNumber = true;
        input = BigInt(input);
      }
      case "bigint": {
        const out = getN(input, countBits(max));
        return wasNumber ? Number(out) : out;
      }
      case "string": {
        wasString = true;
        input = input.split("");
      }
      case "object": {
        if (!Array.isArray(input)) {
          throw new Error("objects are not supported here");
        }
        if (typeof count != "number" && typeof count != "bigint") {
          throw new Error("you need to specify a count");
        }
        const contentCount = BigInt(input.length);
        const bitCount = countBits(contentCount);
        const out = [...Array(count)].map(_=> {
          return input[getN(contentCount, bitCount)];
        });
        return wasString ? out.join("") : out;
      }
    }
  };
})();

random("such String", 20); would return a string with 20 characters randomly made out of the given input string.
like: "r gsuhuSrtrguintughc"
random("10", 20) would generate random bits as string: "10011001011000111010"

if you provide an array, it will also return an array:
random("The quick brown Fox jumps over the lazy Dog".split(" "), 5);
returns something like:
["over","The","Dog","Fox","over"]

now the mindblow.. when using an array, the type of the content is interchangable. you can use objects, numbers, what ever you like.

now.. how to random sort an array with this you may ask..

there you go:

const randomSort = function(array) {
  const tmp = [];

  while(array.length > 0) tmp.push(array.splice(random(array.length), 1)[0]);

  array.push(...tmp);
  return array;
};
};

const array = ["foo", "bar", "asdfg", "rofl", "lol"];
randomSort(array);
console.dir(array); // something like: ["asdfg","bar","lol","rofl","foo"]

i was a bit too lazy to write a class for this.
also const buffer = new Uint8Array(32); could be reduced to const buffer = new Uint8Array(1); but i GUESS calling crypto.getRandomValues will in itself cause a performance penalty while buffering a little bit for the future is probably slightly faster.
just a guess though. i did not benchmark this.

also sorry for not providing comments here. i just made this code out of the blue. simple braingasm.

while using Math.pow and Math.min i was getting "bigint cannot be converted to number" issues thus i just wrote them with ternary.

keep in mind, the buffer usage will differ each run.
it is throwing out bit sequences that were exceeding the amount of items inside the input data.

also sadly there is no log2 in javascripts native bigint yet so i cannot count bits efficiently.

oh and ofc it works with emoji too:
random(["🍕","🚔","🎉","✔","🎁","💩"], 20).join("");
returns something like: 🚔💩✔🎁🎉🚔💩🎁🚔🎁🎁🍕💩🍕🎉🚔🚔🎉🚔🎁

oh and @MelodicCrypter you might like this :D

@kevinbeal
Copy link

very clever, great, nice, thank you, awesome

@rienheuver
Copy link

Love the simplicity, exactly what I needed

@jsvptf22
Copy link

@tbanik really good

@tiagomatosweb
Copy link

Nice!

@gnanakeethan
Copy link

Nice and shortest.

@sempostma
Copy link

sempostma commented Feb 28, 2020

Silly oneliners:

[a-zA-Z0-9]:

for(var a = ''; a.length < 40;) a += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"[(Math.random() * 60) | 0]

[0-z]

String.fromCharCode.apply(0, Array(40).fill(0).map(() => Math.random() * 74 + 42) | 0)

[0-9a-z]

for(var a = '', b = 36; a.length < 40;) a += (Math.random() * b | 0).toString(b)

[0-9A-Z]

for(var a = ''; r = Math.random() * 42, a.length < 40;) a += r < 10 || r > 16 ? String.fromCharCode(48 + r | 0) : ''

@radicand
Copy link

Using crypto: crypto.randomBytes(32).toString('base64'), adjust the parameter to randomBytes for the length you need.

@josuerodcat90
Copy link

Perfect, thank you!

@rherugu
Copy link

rherugu commented May 14, 2020

nice

@abhidp
Copy link

abhidp commented Jul 25, 2020

[...Array(10)].map(i=>(~~(Math.random()*36)).toString(36)).join('')

this is a little better, you can specify any length 💪

where is the i being used? better off providing an empty function like this?

const randomString = (length) => [ ...Array(length) ].map(() => (~~(Math.random() * 36)).toString(36)).join('');

console.log(randomString(14));

@mmRoshani
Copy link

that's good, thanks😊

@jwpjrdev
Copy link

jwpjrdev commented Sep 3, 2020

So simple, so useful.

@pparadoxx
Copy link

thank you so much 👍

@VhMuzini
Copy link

VhMuzini commented Oct 5, 2020

Thank you

@MisaGu
Copy link

MisaGu commented Oct 6, 2020

Array.from({length:10}, () => String.fromCharCode(String(parseInt(65 + Math.random() * (122 - 65))).replace(/9[1-6]/,'90'))).join('')

@abhijit666
Copy link

Is there any simple way to generate string without numbers in it?

@jonathan-annett
Copy link

Is there any simple way to generate string without numbers in it?

const randcharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

const randchars = (function (R,M) {
    var L = R.length,r=M.random, f= M.floor;
    return function (len) {
        var i,s="";
        for (i=0;i<len;i++) s += R[f(r() * L)];
        return s;
    };
})(randcharset.split(''),Math);

for example

document.write("hello:"+randchars(4));

@adam-cyclones
Copy link

"doadiahdoiawd"

Of course you would have to type sporadically every time but I believe this is the fastest performing solution.

@s3rgeym
Copy link

s3rgeym commented Jan 26, 2021

// only printable
Array(8).fill().map(_ => String.fromCharCode(33 + Math.random() * (127 - 33))).join('')

@migue802
Copy link

Noice. 👌 Thanks!!

@usayamadx
Copy link

Awesome!!!

@BlueProgrammer212
Copy link

Pretty cool!

@KnJbMfLAgdkwZL
Copy link

Brilliant!

@Montazu
Copy link

Montazu commented Jan 6, 2022

This is my version. Generate random string with numbers, lower and upper case.

const randomString=length=>Math.random().toString(36).substr(2,length).split("").map(e=>Math.random()<Math.random()?e.toUpperCase():e).join().replaceAll(",","");

console.log(randomString(10)); //8itPVoPBdU

@ughitsaaron
Copy link

Using recursion with the option of providing a prefix.

function randomStr(minLength = 0, acc = '') {
    if (acc.length <= minLength) {
        const str = Math.random().toString(36).slice(2);
        return randomStr(minLength, acc.concat(str))
    }

    return acc.slice(0, minLength);
}

randomStr(10) // => 'fvaj2hm2na'
randomStr(30, 'https://short.codes/') // => 'https://short.codes/jtmx66qr06'

@zeelkakdiya
Copy link

  const idString = async (string_length) => {
    var random_str = "";
    var characters =
      "ABCDEFGHIJKLMNOPQRSTUVWXYZqeytrpolkadjsghfgmnbzxcvnQPOWEYRKASJHDGFMNBCVX--___-_jsfhrlg-_124903564576986483658fgh4sdfh687e4h897WETHJ68F7G4688471877GFHJFFGJ87469857468746hfghwrtiyj4598yhdjkhgnk";
    for (let index = 0; index < string_length; index++) {
      random_str += characters.charAt(
        Math.floor(Math.random() * characters.length)
      );
    }
    let string = `${random_str}`;
    console.log(string);
    return string;
  };

@adam-cyclones
Copy link

adam-cyclones commented Jul 6, 2022

@zeelkakdiya constructive feedback to improve this code:

  1. This is not an async function, it does not use promises
  2. var is used rather than let and in some cases const are more appropriate
  3. let string does not need ${}
  4. console.log is not useful in production code and actually slows down this function
  5. let string to return could be removed.
  6. casing is inconsistent
const generateID = (stringLength = 20) => {
    let randomStr = "";
    const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZqeytrpolkadjsghfgmnbzxcvnQPOWEYRKASJHDGFMNBCVX--___-_jsfhrlg-_124903564576986483658fgh4sdfh687e4h897WETHJ68F7G4688471877GFHJFFGJ87469857468746hfghwrtiyj4598yhdjkhgnk";
    for (let index = 0; index < stringLength; index++) {
      randomStr += characters.charAt(
        Math.floor(Math.random() * characters.length)
      );
    }
    return randomStr;
  };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment